<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Venkatesh-Prasad Ranganath</title>
    <description>The latest articles on DEV Community by Venkatesh-Prasad Ranganath (@rvprasad).</description>
    <link>https://dev.to/rvprasad</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F15883%2F054e498a-8859-44b2-b894-babc229e6b4a.jpg</url>
      <title>DEV Community: Venkatesh-Prasad Ranganath</title>
      <link>https://dev.to/rvprasad</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rvprasad"/>
    <language>en</language>
    <item>
      <title>Questions to assess culture (fit) in tech</title>
      <dc:creator>Venkatesh-Prasad Ranganath</dc:creator>
      <pubDate>Fri, 07 Jun 2024 01:40:34 +0000</pubDate>
      <link>https://dev.to/rvprasad/questions-to-identifyassess-culture-fit-in-tech-1d98</link>
      <guid>https://dev.to/rvprasad/questions-to-identifyassess-culture-fit-in-tech-1d98</guid>
      <description>&lt;p&gt;Based on my observations of teams, I compiled the following non-exhaustive list of questions to learn about the culture of a work environment.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Do teams have a list of well-defined values and behaviors that allow them to decide and execute mostly independently?&lt;/li&gt;
&lt;li&gt;How does the work/development environment support prototyping and experimentation?&lt;/li&gt;
&lt;li&gt;How long (or how much effort) does it take to go from idea to deploying a prototype or an alpha version to internal consumers, say, for continuous experimentation and development)?&lt;/li&gt;
&lt;li&gt;Do teams conduct retrospectives? If so, for what scenarios and what happens after retrospectives? If not, why not?&lt;/li&gt;
&lt;li&gt;How do teams ensure accountability for execution and outcomes? What about accountability for decisions? What about accountability for technical debt?&lt;/li&gt;
&lt;li&gt;Would you deem your culture a permission culture or a constraint culture?&lt;/li&gt;
&lt;li&gt;What is the basis of decisions in your teams, e.g., opinions, evidence, tenure of the executor, track record of the executor, or benefits from the effort?&lt;/li&gt;
&lt;li&gt;What is the decision-making credo in your teams, e.g., skin in the game, no one is hurt, put up or shut up, where the buck stops?&lt;/li&gt;
&lt;li&gt;What happens when team X needs feature Q in product P, which team Y owns but cannot build feature Q?&lt;/li&gt;
&lt;li&gt;What is the reward/recognition culture, e.g., promo for having a significant impact or promo for executing long-term projects?&lt;/li&gt;
&lt;li&gt;Were any projects shelved in the last 6–12months? Why were the projects shelved? Who initiated the shelving?&lt;/li&gt;
&lt;li&gt;Who identifies and initiates projects? What is the associated process?&lt;/li&gt;
&lt;li&gt;During work hours, how much time do developers spend learning new knowledge that may not be immediately relevant to their current work?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are no generally right or wrong answers to (all of) these questions. There are different degrees of goodness-of-fit between the provided answers and the expected answers expected to these questions.&lt;/p&gt;

&lt;p&gt;Answering these questions can help employers and prospective employees assess whether they are a good fit.&lt;/p&gt;

&lt;p&gt;To use these questions, prospective employees should identify the answers to these questions that align with their expectations of a reasonable work environment. Then, they can seek answers to these questions in interviews (remember the “do you have any questions for us?” question :)) or when researching about employers.&lt;/p&gt;

&lt;p&gt;Likewise, employers can adapt and adopt these questions in behavioral interviews to assess cultural fit. Before using them, employers should identify the answers that represent their work environment.&lt;/p&gt;

&lt;p&gt;Teams and organizations can benefit from regularly revisiting such questions to assess the culture of their work environment.&lt;/p&gt;

&lt;p&gt;Of course, the above questions will be useless without honest answers :)&lt;/p&gt;

&lt;p&gt;Original post is available &lt;a href="https://medium.com/@rvprasad/questions-to-assess-culture-fit-in-tech-a7cfb2e94382" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>work</category>
      <category>culture</category>
      <category>technology</category>
    </item>
    <item>
      <title>Why (not) Containers?</title>
      <dc:creator>Venkatesh-Prasad Ranganath</dc:creator>
      <pubDate>Tue, 18 Feb 2020 15:08:12 +0000</pubDate>
      <link>https://dev.to/rvprasad/why-not-containers-2j2a</link>
      <guid>https://dev.to/rvprasad/why-not-containers-2j2a</guid>
      <description>&lt;h1&gt;
  
  
  Why?
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;Containers serve as commonly agreed upon deployment unit&lt;/em&gt; between Dev teams and Ops teams. This eliminates the possibility of missing artifacts when a Dev team hands over a program to the Ops team for deployment.&lt;/li&gt;
&lt;li&gt;Containers allow Dev teams to package any software required by the program to be deployed. This eliminates the need to provide a list of required software to the Ops team when providing the program for deployment.&lt;/li&gt;
&lt;li&gt;Containers allow Dev teams to test the deployment of programs independent of the Ops team and the actual deployment environment.&lt;/li&gt;
&lt;li&gt;Containers allow Dev teams to test the program as a deployed unit independent of the Ops team and the actual deployment environment.&lt;/li&gt;
&lt;li&gt;Containers allow Dev teams to decide how the program uses the available resources without worrying about interference from other programs, e.g., conflicting environment vars, conflicting file locations.&lt;/li&gt;
&lt;li&gt;Containers allow Ops teams to manage the deployments by treating deployment units as black boxes (with very few constraints).&lt;/li&gt;
&lt;li&gt;Containers allow Dev teams to use a rich set of tools to define applications (= program + required software) and build container images for deployment. [See &lt;a href="https://landscape.cncf.io/"&gt;Cloud Native Landscape&lt;/a&gt;]&lt;/li&gt;
&lt;li&gt;Containers allow Ops teams to use a rich set of tools to deploy and operate containers. [See &lt;a href="https://landscape.cncf.io/"&gt;Cloud Native Landscape&lt;/a&gt;]&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Specification (Code) and tools enable automation of tasks associated with packaging, deployment, and operation of containers.&lt;/em&gt; This enables automatic detection of issues; possibly before execution of the tasks.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Why not?
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Dev teams have to deal with installation nuances associated with software required by their program.&lt;/li&gt;
&lt;li&gt;Dev teams have to identify and provide resource requirements along with deployment units, e.g., compute, memory, storage capacity, storage bandwidth.&lt;/li&gt;
&lt;li&gt;Ops teams have to ensure optimal resource utilization in the data center while satisfying the resource requirements of the deployed units.&lt;/li&gt;
&lt;li&gt;Ops teams have to manage/eliminate interference between containers via the shared host (execution) environment.&lt;/li&gt;
&lt;li&gt;Specification/Code and tools enable automation of tasks associated with packaging, deployment, and operation of containers. This amplifies issues due to incorrect specification/code.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  How has container technology influenced software development?
&lt;/h1&gt;

&lt;p&gt;The evolution of cloud computing from resource renting to container-driven automation has clearly influenced how we develop and deploy software.&lt;/p&gt;

&lt;p&gt;The primary factor driving this influence is &lt;em&gt;the specification/codification of requirements and tasks associated with packaging, deployment, and operation of containers.&lt;/em&gt; This factor has reduced ambiguity by the adding rigor in the form of structure/syntax and semantics to the information exchanged between Dev teams and Ops teams. The resulting clarity and precision has expedited the identification and fixing of issues in both process and practice. In turn, this has helped improve the last leg of the software development process.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In short, container technology has served as a tool to help with process management in software development.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While the above opinions are informed, they may be flawed, limited, or might have overlooked some aspects. If so, please point out the flaws, limitations, or overlooked aspects by leaving a comment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S.:&lt;/strong&gt; I have (ab)used the term “containers” to mean the current container technology and the execution entities. Sorry!&lt;/p&gt;

&lt;p&gt;[Originally posted &lt;a href="https://medium.com/@rvprasad/why-not-containers-4597e266aa1f"&gt;here&lt;/a&gt;.]&lt;/p&gt;

</description>
      <category>containers</category>
      <category>cloudcomputing</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Implementing View Types in Python</title>
      <dc:creator>Venkatesh-Prasad Ranganath</dc:creator>
      <pubDate>Sun, 12 Jan 2020 03:54:50 +0000</pubDate>
      <link>https://dev.to/rvprasad/implementing-view-types-in-python-5ba2</link>
      <guid>https://dev.to/rvprasad/implementing-view-types-in-python-5ba2</guid>
      <description>&lt;p&gt;In object-oriented languages like Java, C#, or Kotlin, given a type &lt;code&gt;T&lt;/code&gt;, an associated &lt;em&gt;view type&lt;/em&gt; &lt;code&gt;TView&lt;/code&gt; is used to expose a specific view (parts) of an object of type &lt;code&gt;T&lt;/code&gt;. This helps hide implementation details.&lt;/p&gt;

&lt;p&gt;For example, in the following &lt;a href="https://kotlinlang.org/" rel="noopener noreferrer"&gt;Kotlin&lt;/a&gt; example, &lt;code&gt;Ledger&lt;/code&gt; interface is used to provide access to a ledger while hiding the underlying implementation details, i.e., &lt;code&gt;LedgerImpl&lt;/code&gt; provides the functionalities of a ledger and it has a &lt;code&gt;process&lt;/code&gt; and &lt;code&gt;container&lt;/code&gt; members.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Ledger&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LedgerImpl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Ledger&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;container&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// processing&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getLedger&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Ledger&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;c&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LedgerImpl&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;Ledger&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Can we achieve the same in Python?
&lt;/h1&gt;

&lt;p&gt;Yes, we can mimic the above code structure in Python as follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;abc&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ABC&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;defaultdictclass&lt;/span&gt; &lt;span class="nc"&gt;Ledger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ABC&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;passclass&lt;/span&gt; &lt;span class="nf"&gt;_LedgerImpl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Ledger&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_container&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;facade&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Ledger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_LedgerImpl&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While &lt;code&gt;_container&lt;/code&gt; is marked as private by convention (i.e., the name is prefixed with an underscore), callers of &lt;code&gt;facade&lt;/code&gt; can still access &lt;code&gt;_container&lt;/code&gt; in the returned value as Python does not enforce access restrictions at runtime. So, the implementation details are not truly hidden.&lt;/p&gt;

&lt;h1&gt;
  
  
  Can we do better?
&lt;/h1&gt;

&lt;p&gt;(Accidentally) Yes, we can do better. We can use &lt;code&gt;namedtuple&lt;/code&gt; support in Python to realize the view type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;abc&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ABC&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;defaultdict&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NamedTuple&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Ledger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NamedTuple&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;get_value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_LedgerImpl&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Ledger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Ledger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_container&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;facade&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Ledger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_LedgerImpl&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_view&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this implementation, unless we thread our way thru the lambda function created in &lt;code&gt;get_view&lt;/code&gt;, the implementation details stay truly hidden when compared to the previous Python implementation.&lt;/p&gt;

&lt;p&gt;Also, this implementation pattern relies on composition instead of inheritance. While the earlier implementation pattern can be changed to use composition, it still does not truly hide implementation details.&lt;/p&gt;

&lt;h1&gt;
  
  
  When should we use this pattern?
&lt;/h1&gt;

&lt;p&gt;This pattern is ideal to use when implementation details need to be truly hidden.&lt;/p&gt;

&lt;p&gt;And, here’s my yardstick for when should implementation details be truly hidden.&lt;/p&gt;

&lt;p&gt;If the client programs of a library/program will respect the access restrictions communicated via conventions, then this pattern is not helpful/required. This is most likely the case when modules within a library or program act as clients of other modules in a library or program. In these situation, simpler realizations of view types (e.g., the first python example) will suffice.&lt;/p&gt;

&lt;p&gt;On the other hand, if client programs may take dependence on the implementation of a library/program (e.g., for performance reasons) when the current version of the library/program does not support the capabilities need by the client programs, then this pattern can be helpful to truly hide the implementation.&lt;/p&gt;

&lt;h1&gt;
  
  
  Note
&lt;/h1&gt;

&lt;p&gt;I stumbled on this pattern during my coding sessions. Since I found it to be interesting and useful, I blogged about it. That said, as with all patterns, use them only when they are required.&lt;/p&gt;

&lt;p&gt;(Originally posted &lt;a href="https://medium.com/@rvprasad/implementing-view-types-in-python-7bed2d2c2a1c" rel="noopener noreferrer"&gt;here.&lt;/a&gt;)&lt;/p&gt;

</description>
      <category>python</category>
      <category>coding</category>
      <category>programming</category>
      <category>patterns</category>
    </item>
    <item>
      <title>Can I say “I’ll search it up” in technical interviews?</title>
      <dc:creator>Venkatesh-Prasad Ranganath</dc:creator>
      <pubDate>Fri, 13 Dec 2019 08:37:36 +0000</pubDate>
      <link>https://dev.to/rvprasad/can-i-say-i-ll-search-it-up-in-technical-interviews-527h</link>
      <guid>https://dev.to/rvprasad/can-i-say-i-ll-search-it-up-in-technical-interviews-527h</guid>
      <description>&lt;p&gt;Recently, on Linkedin, someone mentioned how a candidate pretty much answered “I’ll search it up” for most questions in a technical interview. I replied “&lt;em&gt;Depending on the context,&lt;/em&gt; searching for information is not a bad answer.” The reason for my reply is, given the current pace of the tech sector and the number of technologies and buzzwords that whiz past us daily, searching is a good way to reduce memorization burden; more so, when the shelf life of these new bits of information (specifically, in terms of relevance, effectiveness, and novelty) is often suspect.&lt;/p&gt;

&lt;p&gt;That said, the context is very important. For example, is the interview for a senior position or a junior position? Is the question about a technology or a topic/concept? Is the question about basics/fundamentals or nuances? Is the question about the abstracts or details? You get the idea. So, in general, where/how do we draw the line?&lt;/p&gt;

&lt;p&gt;Here’s how I draw the line. &lt;em&gt;&lt;strong&gt;Being able to search smartly and being knowledgeable to know what to search for&lt;/strong&gt; are extremely useful skills.&lt;/em&gt; So, if the candidate can &lt;em&gt;provide evidence of these skills and demonstrate that she is knowledgeable about the topics of interest,&lt;/em&gt; then I’ll accept “I’ll search it up” as a valid answer.&lt;/p&gt;

&lt;p&gt;If you are wondering &lt;em&gt;&lt;strong&gt;how can candidates provide evidence of these skills,&lt;/strong&gt;&lt;/em&gt; then they should describe example situations where they used these skills along with how they used them to resolve the situation. Specifically, what did they search for, how did they search for it, why did they search for it, where did it lead them, did they lose their way, how did they get back on track, and so on until they arrived at the final resolution. [Now, “I’ll search it up” doesn’t so easy, right? ;) ]&lt;/p&gt;

&lt;p&gt;As for &lt;em&gt;&lt;strong&gt;how can candidates demonstrate their knowledge about the topics of interest,&lt;/strong&gt;&lt;/em&gt; they should have a good grasp of the fundamentals of the topics of interest — common concepts, common challenges, common constraints, common solutions — and be aware of sources that they could refer to for details. So, grasp of specifics would be a bonus. Also, they should be able build upon and reason using these fundamentals while considering the specific context and constraints provided by the interviewer. This would implicitly require the candidate to be able to reason about different ideas and their combinations. Also, this requires the interviewer to be an active participant in the interview by posing the right questions to unearth the extent of the candidate’s knowledge.&lt;/p&gt;

&lt;p&gt;At the end, as long as the interviewer is committed to asking the necessary questions to uncover the relevant information, “I’ll search it up” answer isn’t an issue. That said, as an interviewee, why would you want to make your interviewer work harder? :)&lt;/p&gt;

&lt;p&gt;Originally posted on &lt;a href="https://medium.com/@rvprasad/can-i-say-ill-search-it-up-in-a-technical-interview-263d2e374a01"&gt;Medium&lt;/a&gt;&lt;/p&gt;

</description>
      <category>interview</category>
      <category>softwaredevelopment</category>
      <category>technical</category>
    </item>
    <item>
      <title>How would you test for coding skills?</title>
      <dc:creator>Venkatesh-Prasad Ranganath</dc:creator>
      <pubDate>Fri, 13 Dec 2019 08:32:44 +0000</pubDate>
      <link>https://dev.to/rvprasad/how-would-you-test-for-coding-skills-21m3</link>
      <guid>https://dev.to/rvprasad/how-would-you-test-for-coding-skills-21m3</guid>
      <description>&lt;p&gt;First off, by &lt;em&gt;&lt;strong&gt;coding skill&lt;/strong&gt;, I mean the ability to translate an abstract description of a solution into clean, efficient, and working code.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In all of the tech-heavy interviews that I have conducted for junior engineer and research assistant positions, I haven’t explicitly checked for coding skills. Instead, I have done the following.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;See if the candidate had CS education/training.&lt;/strong&gt; If so, then they often will be able to hone their coding skill if they come thru the interview as smart problem solvers with good grasp of fundamentals. Of course, as the interviewer, I have vetted the mentioned CS education/training is a sufficient indicator of the required coding skills.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Examine the candidate’s software project portfolio.&lt;/strong&gt; If they don’t have CS education, then I have asked for their software project portfolio, spent time examining the portfolio, and discussed the code (i.e., logic, code patterns, code structure, language features, libraries) in the portfolio projects. I have also asked about development practices, problem constraints, and alternative solutions, and if and how these influenced the code and their coding decisions.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Ask the candidate to study our code base.&lt;/strong&gt; Not everybody has a software project portfolio. Also, neither of the above approaches may provide the required signals, e.g., the candidate hasn’t done Android programming and our code base is all about Android. In such cases, I have shared our code base (of course, being conscious about IP rights) with the candidate and given her ample amount of time to study it along with opportunities to contact my team or me with questions about the code base. Subsequently, I have discussed the code with the candidate to gauge her understanding of both the code and the system at large.&lt;/p&gt;

&lt;p&gt;While this approach cannot directly assess coding skills, it can help assess a candidate’s willingness and ability to read and understand code; specifically, other’s code. It can also help assess a candidate’s ability to reason about and have intelligent conversations about existing systems. Candidates with these skills can easily hone their coding skills (provided they are open to learning new things).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Looking back, the above approaches have worked well for me :)&lt;/p&gt;

&lt;h2&gt;
  
  
  What about take-home coding assignments?
&lt;/h2&gt;

&lt;p&gt;While I have not given take-home coding assignments, I like this practice as it allows candidates to demonstrate their development skills as they would on the job by using commonly used tools and information sources. However, for this to be effective, the interviewer should examine the candidate’s solution. If the solution is good enough, then she should discuss it with the candidate as part of the interview.&lt;/p&gt;

&lt;p&gt;On a related note, &lt;a href="https://dev.to2019-12-11%2015:59:%20Reading:%20Non-Tech"&gt;here are the basic skills&lt;/a&gt; that I think are necessary to be a good software engineer.&lt;/p&gt;

&lt;p&gt;Originally posted on &lt;a href="https://medium.com/@rvprasad/how-would-you-test-for-coding-skills-bc6508dc2df8"&gt;Medium&lt;/a&gt;&lt;/p&gt;

</description>
      <category>interview</category>
      <category>softwaredevelopment</category>
      <category>technical</category>
    </item>
    <item>
      <title>What’s with thinking out loud in technical interviews?</title>
      <dc:creator>Venkatesh-Prasad Ranganath</dc:creator>
      <pubDate>Fri, 13 Dec 2019 08:28:18 +0000</pubDate>
      <link>https://dev.to/rvprasad/what-s-with-thinking-out-loud-in-technical-interviews-2fib</link>
      <guid>https://dev.to/rvprasad/what-s-with-thinking-out-loud-in-technical-interviews-2fib</guid>
      <description>&lt;p&gt;A common requirement in most white-board coding interviews is a candidate voice out her thoughts as she works thru the problem. The same applies to design interviews as well.&lt;/p&gt;

&lt;p&gt;I understand this requirement helps gauge how well a candidate can communicate their thoughts. No doubt this is an an important skill; specifically, in a role that involves lot of interaction.&lt;/p&gt;

&lt;p&gt;That said, I think this requirement imposes quite a bit of wastage.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Not all thoughts associated with problem solving are worthy of communication. &lt;em&gt;Do we really want the candidate to voice every thought?&lt;/em&gt; (Remember verbalizing thoughts is not the same as communicating thoughts.)&lt;/li&gt;
&lt;li&gt;While the ability to be selective about the thoughts to communicate is important, this selection process requires some thinking as well; hence, it shifts the focus away from problem solving. &lt;em&gt;Why force the candidate to shift focus away from problem solving?&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;If the interview is being conducted in English, then many non-native English speaking candidates may likely not think in English. If so, after forming a thought while solving the problem, such candidates will have to expend some mental effort to translate the previous thought into English before saying it. Again, beyond forcing candidates to shift focus away from problem solving, &lt;em&gt;why put non-native English speaking candidates at disadvantage in terms of time?&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;The same applies to visual thinkers. Left to their own devices, they could draw up pictures that capture their thoughts and then explain it. Instead, &lt;em&gt;why ask them to explain the pictures as they are drawing?&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;All candidates are not equal. Due to whatever reasons, some candidates may be more methodical and thorough. This requirement puts unnecessary additional demands on such candidates. Looking at it another way, the requirement asks such candidates to be a bit sloppy in the interest of time. &lt;em&gt;Why demand sloppiness in knowledge-centric domain?&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Have you ever tried talking pretty much continuously for one hour? Now, imagine doing it for couple of hours in a row. &lt;em&gt;Why expend energy on unnecessary talking?&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Beyond the above limitations, I think the requirement is unrealistic as we seldom operate so while working.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does your co-worker loudly explain the design/code that she is creating? If so, do you understand her explanation?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In my experience, even when team members meet to discuss an idea, most of the members who lead the discussion early on would have either 1) thought about and worked on the the problem and their solution or 2) experienced similar situations. As for those who contribute later on in such meetings, they do so after understanding and thinking about the solutions as the solutions are being described and discussed.&lt;/p&gt;

&lt;p&gt;So, if we never think out loud while working, then why require candidates to think out loud?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This requirement seems to focus on the quantity of communication instead of the quality of communication.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Is there an alternative?
&lt;/h2&gt;

&lt;p&gt;To get the most out of the 45–60 minutes of interview time, we can allow candidates to solve the problem as they would do naturally but without the use of information resources. This will paint a more accurate picture of how candidates operate while designing and coding on the job. To ensure candidates do not get stuck or lost, we can use regular prompting. If we are interested in the process of how a candidate arrived at a solution, then we can state this at the beginning of the interview and set aside time to discuss the solution as a whole and in parts along with the choices made while crafting the solution.&lt;/p&gt;

&lt;p&gt;Originally posted on &lt;a href="https://medium.com/@rvprasad/whats-with-thinking-out-loud-in-technical-interviews-26030abc39b5"&gt;Medium&lt;/a&gt;&lt;/p&gt;

</description>
      <category>interview</category>
      <category>technical</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Spectrum of Data Analysis</title>
      <dc:creator>Venkatesh-Prasad Ranganath</dc:creator>
      <pubDate>Fri, 28 Jun 2019 22:47:43 +0000</pubDate>
      <link>https://dev.to/rvprasad/spectrum-of-data-analysis-3fhg</link>
      <guid>https://dev.to/rvprasad/spectrum-of-data-analysis-3fhg</guid>
      <description>&lt;p&gt;&lt;strong&gt;Descriptive analysis&lt;/strong&gt; summarizes the data.&lt;/p&gt;

&lt;p&gt;Given the daily data about fuel consumed by your car, calculating the average daily fuel consumption of your car would qualify as descriptive analysis that summarizes a feature (e.g., daily fuel consumption) of your car.&lt;/p&gt;

&lt;p&gt;Suppose we have the daily data about number of miles traveled by your car, calculating the average daily fuel mileage of your car would also qualify as descriptive analysis. Unlike the determining the average daily fuel mileage, this analysis first combines two features to derive a new feature that further describes/characterizes your car and then summarizes the new feature.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In &lt;strong&gt;descriptive analysis&lt;/strong&gt;, we focus on summarizing either original or derived features of an entity.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Inferential analysis&lt;/strong&gt; extracts information about source entity of the data.&lt;/p&gt;

&lt;p&gt;Continuing the previous example, suppose we also have data about the daily tire pressure of your car. Now, we can try to answer questions such as “does the tire pressure of your car influence the fuel mileage of your car?”, “Is the influence positive or negative?”, and “What is the magnitude of the influence?”&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In &lt;strong&gt;inferential analysis&lt;/strong&gt;, we focus on identifying relationships between features of entities.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In terms of time, inferential analysis is all about what happened in the past. So, the goal is to understand past data and answer questions about events that have occurred.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Predictive analysis&lt;/strong&gt; predicts possible outcomes about the source entity of the data (assuming all things being equal).&lt;/p&gt;

&lt;p&gt;Based on the previous year’s data, we know that the average fuel mileage of your car is 35 miles per gallon. Further, let’s assume we have inferred, for each psi drop in your car’s tire pressure from normal (recommended) tire pressure, your car’s fuel mileage drops by 2 miles per gallon. Now, if the tire pressure of your car is 3 psi below normal, then we can predict that you will be able to cover 290 miles with 10 gallons instead of 350 miles (independent of any previous observations of the tire pressure being 3 psi below normal).&lt;/p&gt;

&lt;p&gt;Of course, the above prediction hinges on all things being equal. In other words, the prediction can go wrong if either the weather gets way colder or hotter than usual or the road you take is bumpier than usual or the traffic is slower than usual or any other reasons that can affect the prediction but have not been captured in the data or considered in the analysis.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In &lt;strong&gt;predictive analysis&lt;/strong&gt;, assuming all things being equal, we focus on predicting the features of entities based on the inferred relationships between the features of entities. So, in some sense, predictive analysis is an extension of inferential analysis as the results of inference are used for prediction.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In terms of time, predictive analysis is kinda the dual of inferential analysis as it is all about what could have happened or can happen, i.e., both alternative past events that did not occur or possible future events. The goal is to understand past data and answer questions about events that have not occurred.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prescriptive analysis&lt;/strong&gt; uses the data to prescribe actions that can lead to desired outcome (assuming all things being equal).&lt;/p&gt;

&lt;p&gt;Equipped with the results from the previous predictive analysis and the list of possible actions to increase tire pressure, we can now prescribe an action or a ranked list of actions to get good fuel mileage. So, if you mention that your fuel mileage is below (normal) 35 miles per gallon, then we can ask if the tire pressure is lower than normal? If you reply “yes, it is 24 psi instead of the normal tire pressure of 27 psi”, then we can prescribe that you increase the tire pressure by 3 psi (to 27 psi) to get normal fuel mileage.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In &lt;strong&gt;prescriptive analysis&lt;/strong&gt;, we focus on prescribing actions to manipulate the features of entities to effect changes in features of entities. This aspect of manipulating the entities to effect desired future outcomes is a definitive aspect of prescriptive analysis.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In terms of time, unlike inferential analysis and predictive analysis, prescriptive analysis is all about what can happen in the future. The goal is to understand past data and prescribe actions that can lead to desired future events.&lt;/p&gt;

&lt;p&gt;(This is minor edited version of &lt;a href="https://medium.com/@rvprasad/spectrum-of-data-analysis-7ffa754c06fc"&gt;this original post&lt;/a&gt;.)&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>dataanalysis</category>
      <category>dataanalytics</category>
    </item>
    <item>
      <title>Covariance and Contravariance</title>
      <dc:creator>Venkatesh-Prasad Ranganath</dc:creator>
      <pubDate>Sun, 21 Apr 2019 04:59:23 +0000</pubDate>
      <link>https://dev.to/rvprasad/covariance-and-contravariance-4a1c</link>
      <guid>https://dev.to/rvprasad/covariance-and-contravariance-4a1c</guid>
      <description>&lt;p&gt;In the below &lt;a href="https://kotlinlang.org/"&gt;Kotlin&lt;/a&gt; code snippet, &lt;em&gt;Producer class is covariant in type parameter T&lt;/em&gt; and &lt;em&gt;Consumer class is contravariant in type parameter T&lt;/em&gt;. In other words, &lt;em&gt;T is a covariant type parameter of Producer&lt;/em&gt; and &lt;em&gt;T is a covariant type parameter of Consumer&lt;/em&gt;. So, what do these statements mean?&lt;/p&gt;

&lt;p&gt;To understand the meaning of these statements, let’s consider the allowed behaviors. Copy-n-paste the above code snippet at &lt;a href="https://try.kotlinlang.org"&gt;https://try.kotlinlang.org&lt;/a&gt; and run it. You will observe two errors — at lines 13 and 15.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Covariance
&lt;/h2&gt;

&lt;p&gt;The assignment on line 11 is allowed as &lt;code&gt;Producer&amp;lt;Double&amp;gt;&lt;/code&gt; is treated as a sub-type of &lt;code&gt;Producer&amp;lt;Number&amp;gt;&lt;/code&gt;. This is due to two reasons.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Values of type &lt;code&gt;T&lt;/code&gt; can &lt;em&gt;only be retrieved/read from&lt;/em&gt; &lt;code&gt;Producer&amp;lt;T&amp;gt;&lt;/code&gt; instances because &lt;code&gt;T&lt;/code&gt; is used &lt;em&gt;to specify only the values provided by&lt;/em&gt; &lt;code&gt;Producer&lt;/code&gt;; see the class definition of &lt;code&gt;Producer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Since &lt;code&gt;Producer&amp;lt;Double&amp;gt;&lt;/code&gt; instance is assigned to &lt;code&gt;p1&lt;/code&gt;, all values retrieved/read via &lt;code&gt;p1&lt;/code&gt; will be of type &lt;code&gt;Double&lt;/code&gt;, a sub-type of the type argument &lt;code&gt;Number&lt;/code&gt; of the declared type &lt;code&gt;Produce&amp;lt;Number&amp;gt;&lt;/code&gt; of &lt;code&gt;p1&lt;/code&gt;. So, the behavior exhibited by the instance assigned to &lt;code&gt;p1&lt;/code&gt; conforms with (is a subset of) the behavior guaranteed by the declared type of &lt;code&gt;p1&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Due to the above sub-typing relation, the assignment on line 13 is not allowed. If it was allowed, &lt;code&gt;p2.read()&lt;/code&gt; would return a value of type &lt;code&gt;Number&lt;/code&gt; when it should return only values of type &lt;code&gt;Double&lt;/code&gt; based on the declared type &lt;code&gt;Producer&amp;lt;Double&amp;gt;&lt;/code&gt; of &lt;code&gt;p2&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contravariance
&lt;/h2&gt;

&lt;p&gt;A similar reasoning explains contravariance.&lt;/p&gt;

&lt;p&gt;The assignment on line 17 is allowed as &lt;code&gt;Consumer&amp;lt;Number&amp;gt;&lt;/code&gt; is treated as a sub-type of &lt;code&gt;Consumer&amp;lt;Double&amp;gt;&lt;/code&gt;. This is due to two reasons.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Values of type &lt;code&gt;T&lt;/code&gt; can &lt;em&gt;only be injected/written into&lt;/em&gt; &lt;code&gt;Consumer&amp;lt;T&amp;gt;&lt;/code&gt; instances because &lt;code&gt;T&lt;/code&gt; is used &lt;em&gt;to specify only the values provided to&lt;/em&gt; &lt;code&gt;Consumer&lt;/code&gt;; see the class definition of &lt;code&gt;Consumer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Since the type argument &lt;code&gt;Double&lt;/code&gt; of the declared type of &lt;code&gt;c2&lt;/code&gt; is a sub-type of &lt;code&gt;Number&lt;/code&gt;, all values provided to &lt;code&gt;Consumer&amp;lt;Number&amp;gt;&lt;/code&gt; instance assigned to &lt;code&gt;c2&lt;/code&gt; will be a sub-type of type &lt;code&gt;Number&lt;/code&gt;. The behavior allowed by the declared type of &lt;code&gt;c2&lt;/code&gt; conforms with (is a subset of) the behavior supported by the instance assigned to &lt;code&gt;c2&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Due to the above sub-typing relation, the assignment on line 15 is not allowed. If it was allowed, &lt;code&gt;c1.write(3)&lt;/code&gt; would store a value of type &lt;code&gt;Number&lt;/code&gt; in the property (field) &lt;code&gt;c1.e&lt;/code&gt; when it should store only values of type &lt;code&gt;Double&lt;/code&gt; in &lt;code&gt;c1.e&lt;/code&gt; based on the &lt;code&gt;Consumer&amp;lt;Double&amp;gt;&lt;/code&gt; instance assigned to &lt;code&gt;c1&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In short, if type &lt;code&gt;X&lt;/code&gt; is a sub-type of type &lt;code&gt;Y&lt;/code&gt; and type &lt;code&gt;S&amp;lt;X&amp;gt;&lt;/code&gt; can be treated as sub-type of type &lt;code&gt;S&amp;lt;Y&amp;gt;&lt;/code&gt;, then &lt;code&gt;S&lt;/code&gt; is &lt;strong&gt;covariant&lt;/strong&gt; in &lt;code&gt;T&lt;/code&gt; and &lt;code&gt;T&lt;/code&gt; is a &lt;strong&gt;covariant type parameter&lt;/strong&gt; of the generic type &lt;code&gt;S&amp;lt;T&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Similarly, if type &lt;code&gt;X&lt;/code&gt; is a sub-type of type &lt;code&gt;Y&lt;/code&gt; and &lt;code&gt;S&amp;lt;Y&amp;gt;&lt;/code&gt; can be treated as sub-type of type &lt;code&gt;S&amp;lt;X&amp;gt;&lt;/code&gt;, then &lt;code&gt;S&lt;/code&gt; is &lt;strong&gt;contravariant&lt;/strong&gt; in &lt;code&gt;T&lt;/code&gt; and &lt;code&gt;T&lt;/code&gt; is a &lt;strong&gt;contravariant type parameter&lt;/strong&gt; of the generic type &lt;code&gt;S&amp;lt;T&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In both definitions, the key is if &lt;code&gt;S&amp;lt;X&amp;gt;&lt;/code&gt; will be treated as sub-type of &lt;code&gt;S&amp;lt;Y&amp;gt;&lt;/code&gt; or vice versa, and this  is dependent on how the type parameter &lt;code&gt;T&lt;/code&gt; of &lt;code&gt;S&amp;lt;T&amp;gt;&lt;/code&gt; is used in &lt;code&gt;S&lt;/code&gt;; specifically, in the context of input and output of the operations/methods of &lt;code&gt;S&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kotlinlang.org/docs/reference/generics.html#variance"&gt;https://kotlinlang.org/docs/reference/generics.html#variance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Chapter 11 of &lt;a href="https://www.amazon.com/Fundamentals-Object-Oriented-Design-Meilir-Page-Jones/dp/020169946X/"&gt;Fundamentals of Object-Oriented Design in UML&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>programminglanguages</category>
      <category>kotlin</category>
      <category>coding</category>
    </item>
    <item>
      <title>How to be a Good Reviewer?</title>
      <dc:creator>Venkatesh-Prasad Ranganath</dc:creator>
      <pubDate>Sun, 02 Sep 2018 17:21:23 +0000</pubDate>
      <link>https://dev.to/rvprasad/how-to-be-a-good-reviewer-3l5b</link>
      <guid>https://dev.to/rvprasad/how-to-be-a-good-reviewer-3l5b</guid>
      <description>&lt;p&gt;Independent of the artifact being reviewed (e.g., design doc, code, test, packaging, presentation, book), a good reviewer should do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identify issues in the artifact &lt;strong&gt;(What)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Provide reasons why an issue is an issue &lt;strong&gt;(Why)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Suggest how to fix the identified issues &lt;strong&gt;(How)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It is not sufficient to merely do 1 and 3.  It is necessary to do 2 to &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;assess the validity of your judgement and&lt;/li&gt;
&lt;li&gt;help authors learn and improve.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here are two examples:&lt;/p&gt;

&lt;h4&gt;
  
  
  Example 1 (Code)
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;This field access could lead to a null pointer exception.&lt;/li&gt;
&lt;li&gt;The receiver in the field access expression is the object returned from this method call which can return null.&lt;/li&gt;
&lt;li&gt;Ensure the receiver object is non-null before accessing the field.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Example 2 (Documentation)
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;The instruction is asking the user to set up an emulator.&lt;/li&gt;
&lt;li&gt;The user may not know how to set up an emulator.&lt;/li&gt;
&lt;li&gt;Provide instructions to set up an emulator or explicitly mention the user should be familiar with setting up an emulator.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>review</category>
      <category>reviewer</category>
      <category>code</category>
      <category>documentation</category>
    </item>
    <item>
      <title>Donts and Dos for Conversations (and Interactions)</title>
      <dc:creator>Venkatesh-Prasad Ranganath</dc:creator>
      <pubDate>Sun, 19 Aug 2018 04:20:49 +0000</pubDate>
      <link>https://dev.to/rvprasad/dos-and-donts-for-conversations-and-interactions-51jp</link>
      <guid>https://dev.to/rvprasad/dos-and-donts-for-conversations-and-interactions-51jp</guid>
      <description>&lt;ol&gt;
&lt;li&gt;Don’t equate modesty with lack of expertise.&lt;/li&gt;
&lt;li&gt;Don’t equate chattiness with expertise.&lt;/li&gt;
&lt;li&gt;Don’t equate silence with lack of leadership.&lt;/li&gt;
&lt;li&gt;Don’t equate loudness with leadership.&lt;/li&gt;
&lt;li&gt;Don’t equate directness with rudeness.&lt;/li&gt;
&lt;li&gt;Don’t equate questions with insubordination.&lt;/li&gt;
&lt;li&gt;Don’t equate questions with disagreement.&lt;/li&gt;
&lt;li&gt;Don’t equate politeness with agreement.&lt;/li&gt;
&lt;li&gt;Don’t be a time hog.&lt;/li&gt;
&lt;li&gt;Don’t wing it. Be prepared.&lt;/li&gt;
&lt;li&gt;Be considerate.&lt;/li&gt;
&lt;li&gt;Don’t be submissive.&lt;/li&gt;
&lt;li&gt;Don’t be domineering.&lt;/li&gt;
&lt;li&gt;Don’t jump to conclusion. Instead, seek clarification.&lt;/li&gt;
&lt;li&gt;Have a conversation — listen, reason, speak, repeat.&lt;/li&gt;
&lt;li&gt;Don’t interrupt when someone is speaking.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it for now :)&lt;/p&gt;

</description>
      <category>softskills</category>
      <category>conversations</category>
    </item>
    <item>
      <title>Static Typing vs Testing == Apples vs Oranges</title>
      <dc:creator>Venkatesh-Prasad Ranganath</dc:creator>
      <pubDate>Tue, 31 Jul 2018 10:14:46 +0000</pubDate>
      <link>https://dev.to/rvprasad/static-typing-vs-testing--apples-vs-oranges-5cbn</link>
      <guid>https://dev.to/rvprasad/static-typing-vs-testing--apples-vs-oranges-5cbn</guid>
      <description>&lt;p&gt;I have heard discussions about why static typing is superior to testing (and vice versa) as the way to lower the number of bugs in systems, and I think such discussions are futile as they are comparing apples and oranges.&lt;/p&gt;

&lt;p&gt;Consider the following program fragment (in Python with type hints).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If we consider only the type signatures of these functions, then we have the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;
&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Using only type signatures, we can flag the following invocations as faulty.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# first argument is not of int type
&lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# second argument is not of int type
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;However, type signatures are not sufficient to flag the following invocations as faulty.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"val1 is equal to val2"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"val1 is less than val2"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, we might think that these faults would not have occurred if the functions were named as &lt;code&gt;equals&lt;/code&gt; and &lt;code&gt;less_than&lt;/code&gt;. By renaming, observe that we are not relying on static typing to avoid the faults :)&lt;/p&gt;

&lt;p&gt;Nevertheless, let’s go ahead and rename the functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;less_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"val1 is equal to val2"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;less_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"val1 is less than val2"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Even now, the code fragment is faulty.&lt;/p&gt;

&lt;p&gt;The issue is there are (at least) two kinds of types and we have only specified only one kind of type. For the other kind of type, we are relying on the association between function names and expected function behaviors.&lt;/p&gt;

&lt;p&gt;To understand the issue, consider the description of &lt;code&gt;equals&lt;/code&gt; function:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Accepts two integer values i and j and returns a boolean value.&lt;/li&gt;
&lt;li&gt;Returns true if the inputs are equal; false otherwise.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first part of the description constrains the values that are valid as input to and output from the function. This description is the value (domain) type of the function, which we specified using type hints (e.g., : int).&lt;/p&gt;

&lt;p&gt;The second part of the description constrains the behavior of the function. This kind of description is the behavioral type of the function (one that can be realized in different ways). In the example above, we did not specify this kind of type information.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Static typing as available in most programming languages today are geared towards only specifying value types (and not behavioral types).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you are still not convinced about behavioral types, then consider relying on just the function signature &lt;code&gt;(List[int]) -&amp;gt; List[int]&lt;/code&gt; and picking a function that sorts a given list of integers in ascending order.&lt;/p&gt;

&lt;h1&gt;
  
  
  What about testing?
&lt;/h1&gt;

&lt;p&gt;Unlike static typing (as it is generally available today), testing is not about value types.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Testing is about specifying and checking behavioral types.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Specifically, a test case captures a specific behavior of a function (e.g., &lt;code&gt;equals(3,3)&lt;/code&gt; should evaluate to true, &lt;code&gt;equals(3,5)&lt;/code&gt; should evaluate to false), a test suite captures the behavioral type (i.e., a collection of expected behaviors) of a function, and testing checks if an implementation of a function is behaviorally type correct (i.e., function exhibits the expected behaviors).&lt;/p&gt;

&lt;p&gt;To draw parallels with static typing, test suites are similar to type hints and testing is similar to type checking.&lt;/p&gt;

&lt;p&gt;While testing may seem better than static typing, it is not the case. Unlike static typing, tests are neither succinct nor exhaustive in specifying the possible behaviors of a function under test (in general). This is true even with enhanced testing techniques such as property-based testing. Further, using testing as a way to ensure value type correctness is prohibitive in general.&lt;/p&gt;

&lt;h1&gt;
  
  
  So, where does this leave us?
&lt;/h1&gt;

&lt;p&gt;Until the day we have static type systems that allow us to easily and succinctly specify both value and behavioral types and use them to check for type correctness, we will need both static typing and testing to lower the number of bugs in systems.&lt;/p&gt;

&lt;p&gt;In short, static typing and testing are complementary. And, for now, we need to be able to specify and reason with types and create and execute tests.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>testing</category>
      <category>statictyping</category>
      <category>bugs</category>
    </item>
    <item>
      <title>Returning to Linux after 10 years</title>
      <dc:creator>Venkatesh-Prasad Ranganath</dc:creator>
      <pubDate>Wed, 02 May 2018 00:16:50 +0000</pubDate>
      <link>https://dev.to/rvprasad/returning-to-linux-after-10-years-dc0</link>
      <guid>https://dev.to/rvprasad/returning-to-linux-after-10-years-dc0</guid>
      <description>&lt;p&gt;After close to a decade of using Windows and MBP for development, I recently switched back to Linux as my development platform. For this, I chose to run PopOS! on &lt;a href="https://system76.com/laptops/oryx" rel="noopener noreferrer"&gt;Oryx Pro&lt;/a&gt; laptop from &lt;a href="https://system76.com/" rel="noopener noreferrer"&gt;System76&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Oryx Pro
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flcrhijg3ke0fuxri8zot.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flcrhijg3ke0fuxri8zot.jpeg" alt="An image of Oryx Pro" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In terms of capabilities, Oryx Pro is very impressive. It can house a NVidia GeForce 1060 or 1070, up to 64GB RAM, and a whooping 10TB of storage space!!&lt;/p&gt;

&lt;p&gt;While it is not from a big company (e.g., Dell, Lenovo), it is well-built, sleek, and sturdy. In terms of what we have come to expect of form factors of laptops, it is a bit bulky; especially, if one is switching over from MBP. However, it compensates pretty generously in terms of capabilities.&lt;/p&gt;

&lt;p&gt;In terms of experience, everything worked seamlessly out of the box. No hiccups or DOA. Customer service and tech support at System76 have been very helpful.&lt;/p&gt;

&lt;p&gt;As with life, no experience is without warts :) After few days of using the laptop, I realized there were three major annoyances.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The power port accepts a L-shaped power plug and it is right next to the HDMI port. Hence, when the HDMI port is occupied, the power plug cannot rotate 360 degrees. So, there may be undue pressure on HDMI port and power port due to the interaction between the plugs. I suspect an accidental tug could cause non-trivial damage. A straight power plug can easily solve this problem. [&lt;em&gt;Update&lt;/em&gt;: Using a mini-display port located away from the power port solved this problem.]&lt;/li&gt;
&lt;li&gt;The integrated Intel GPU is not hooked up to any of the three external display port. This means NVidia GPU is not available as a dedicated compute GPU when hooked to an external monitor, which is when one would want to use a dedicated GPU for compute purpose.&lt;/li&gt;
&lt;li&gt;A single battery charge lasts for less than 90 minutes. This is way less compared to that of a Macbook Pro under similar workload when hooked on to an external monitor (driven by NVidia GPU). I wonder if this would have been the case if Intel GPU could drive external monitors. So far, I have been trying various tweaks and they seem to be making some difference. I need to run more test to confirm the observed difference is both sustained and substantial.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even with the above annoyances, if you are looking for a configurable dev-ready laptop (CPU and GPU) at a reasonable price, then I’d happily recommend Oryx Pro. Just talk to the sales/tech team at System76 and validate your assumptions before ordering your laptop.&lt;/p&gt;

&lt;h1&gt;
  
  
  Pop OS!
&lt;/h1&gt;

&lt;p&gt;My past experience with Linux is, if you can find and configure appropriate device drivers and applications and get them to play nice with each other, then Linux is developer’s heaven. The finding and configuring was always the pickle. Pleasantly, this does not seem to be the case today.&lt;/p&gt;

&lt;p&gt;Oryx Pro came pre-installed with &lt;a href="https://system76.com/pop" rel="noopener noreferrer"&gt;Pop OS!&lt;/a&gt;, a &lt;a href="https://www.ubuntu.com/desktop/1710" rel="noopener noreferrer"&gt;Ubuntu 17.10&lt;/a&gt; based distribution. Upon switching on the Oryx Pro, all devices in the laptop were operational and available to be used via software. Fn+F10 toggled the webcam. VLC was able to show the feed from the webcam. USB ports operated at their top speeds without any changes to kernel flags. GPU was recognized with no issue. External HDDs, monitors, keyboards, and trackballs (yes!) were recognized with zero tweaks . I could configure the trackball keys in under 2 minutes. I was able to configure Gnome/X display to span across multiple monitors. Within 3 hours, I had the laptop configured with all of the required software (including downloading them from the web). Yes, I had arrived at my developer heaven :)&lt;/p&gt;

&lt;p&gt;Then, I faced two issues.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I started setting up my personal app-specific preferences. Unlike on a PC or or a MBP, I had to manually identify and copy relevant configuration files from a different machine. This took some time for two reasons: a) this was a once-in-a-while kinda task that I was rusty with and it required quite a few web look ups, and b) there were no applications to do migrate my app-specific preferences between Linux and PC/MBP. Since this is an infrequent task, I consider it as a minor convenience.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I started playing with NVidia Settings app to switch between Intel GPU profile and NVidia GPU profile. While the app required me to logout for the switch to take effect, I had to reboot the laptop for the switch to take effect. IMO, this is a major annoyance. &lt;/p&gt;

&lt;p&gt;Now, it is possible that I may be doing something wrong here and all that is required is indeed logout and login. Even so, it is still a major inconvenience if one has many apps running at the time of such a switch.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Despite these issues, it was very refreshing to be back on a platform where I can easily install apps from binaries or build apps from sources and get on with my work. [To appreciate this feeling, one should try to install libraries for Python from source on Mac and Windows.]&lt;/p&gt;

&lt;p&gt;While I will need to use a PC or a MBP from time to time for specific tasks (cos’ they are easier and better-supported on a PC or a MBP), I am currently a happy to be back on Linux for development.&lt;/p&gt;

&lt;p&gt;[Note: The original post appeared &lt;a href="https://medium.com/@rvprasad/returning-to-linux-after-10-years-e4944acddbd3" rel="noopener noreferrer"&gt;here&lt;/a&gt;.]&lt;/p&gt;

</description>
      <category>linux</category>
      <category>development</category>
      <category>laptop</category>
    </item>
  </channel>
</rss>
