Monday, August 20, 2012

Core Java Must Knows


Have attended as well as taken couple of Java tech interviews over the course of my career, some good some not so good either ways.

However what baffles me the most is that lot of folks that I had evaluated seem to stumble on the very basic core concepts, these are profiles with a good 8 to 10 years of Java experience and when asked how many constructors does java.lang.Object class have they go hmm..... None or 1 or 2  or famously do not remember, come on - we call ourselves Java professional the least we can do give java.lang.Object some respect after all its the big daddy of all java classes.

Will try to sum up some of the basic core Java concepts that I personally feel every Java professional should know, again these are solely my opinions based on my reading and posts over the internet, please feel free to comment on others that you feel are important as well.

1. Know your Object

 
    From the JavaDocs - "Class Object is the root of the class hierarchy. Every class has Object as a 
    superclass. All objects, including arrays, implement the methods of this class"
 
    Object class has 1 default no-arg constructor.

    Methods from Object class which one should know top of their head- toString() equals() hashCode()
    finalize() clone() getClass() wait() notify()
 
    Rules for the equals method - reflexive symmetric transitive consistent. Josh Bloch's Effective 
    Java talks superbly about equals and hashCode. A must have for every Java Professional.
 
    What does hashCode method do - Its returns a hashCode, a generated integer/long value which    
    by default is obtained by converting the internal address of the object into an integer. HashCode aids  
    when the objects are stored in hash based collections - HashMap, HashTables. Hashing it Out a nice one
    I came across about equals and hashCode.   
   

2. Know your Access Modifiers


Yes the code shown is very valid Java code, yet many fell for the private static final trap.

Need to clearly understand that the reference variable aMap is final, however the Map itself  is not and can be manipulated.

We are aware of public, private, protected and default (friendly) access modifiers, not just what they are but understand their practicalities. Familiarize with Access Modifiers if not done in a while.

3. Know your Memory

 
    Java Memory Model includes the Heap and  Stack. Stack is the memory allocation where methods     
    and local variables live, these are generally short lived. Heap is where Objects and member variables or
    instance variables live these generally live longer. Java 6 though may have some optimization and the JVM
    may allocate objects on the stack.

    In multi-threaded programs, each thread will have its own stack allocations but all threads will share a
    common heap, so need to be extra cautious when dealing with mutable objects all residing on the same
    shared heap.    

    Heap is divided into Eden, Survivor Spaces, Old Generation and Perm Generation.
 
    Eden - When new Objects are created memory allocation first takes place in the Eden.
     
    Survivor Spaces - As the Objects survive Garbage Collection they move to Survivor spaces, there are 2
    of them from and to Survivor Spaces.
 
    Eden and the Survivor spaces together make up the Young Generation or Young gen for short.
 
    Old Generation - As the Survivor spaces gets crowded, older objects move to the Old Generation.
    These are objects which have survived multiple GC's, hence "old" generation as in OLD objects.
 
    Perm Generation - This stores  VM and Class Meta Data Details, these are used internal by the  
    VM. Perm Gen is in the process of being eliminated, Java 8 may no longer support Perm Gen moving
    forward.
 
    Java Heap is nothing but the combination of the Young Gen and Old Gen. Minor GC's happen when
    Objects are reclaimed or move from Eden to the Survivor Spaces. Major GC's (Stop the World
    GC) happens when Old Gen starts getting over crowed and memory needs to be freed. There are lot of
    implications in the way we create our Objects. Even though we do not directly deal with memory we still
    have to be very conservative when creating and maintaining object references in our programs, after all
    nothing is really free in this world, there's always a catch.

    Charlie Hunt's - Java Performance Talk, an excellent talk about Java Performance tuning has a very nice
    intro to the Java Memory Model.
 

4. Know your Collections

 
    Java Collections are data structures that allow you to easily work and manipulate collection of data. They
    pretty easy to use and probably the best example of re-use, cannot think of any real world java  
    applications  that can do without the use of collections.

    Collections API is made up of 7 core interfaces (Collection, Set, SortedSet, List, Queue, Map,
    SortedMap)
 
    Collection interface is the root interface of the collection hierarchy. A Collection contains groups of
    objects which are called as elements. Set, List and Queue are sub-interfaces from the root Collection
    interface.

    Set is a collection that cannot contain duplicate elements, models the mathematical set construct to
    represents sets like a deck of cards comprising a poker hand. When objects are stored in a set collection
    the equals and hashCode methods must be correctly overridden to make sure that objects obey set
    construct rules.  
 
    SortedSet is a special kind of set which maintains its unique elements in an ascending order or natural
    ordering of the elements. A comparator may also be used at creation time of the sorted set when sorting
    the elements.

    List is an ordered or sequenced collection of elements. Lists can contain duplicate elements. The order in
    which the elements are added to the list are maintained. List provides for positional indexed access to list
    elements. SubList returns a view of the portion of this list between the specified fromIndex, inclusive, and  
    toIndex, quite handy when dealing with large lists and concurrent implementations.
 
    Queue is a collection that holds multiple elements prior to processing, think of Queue literally like a queue
    or line at a bus stand, by default people standing in the queue get into the bus in the order they are in
    the queue. Queues by default order elements in a FIFO (first-in, first-out) manner
 
    Map is a type of collection in which elements are stored using keys. Map cannot contain duplicate keys
    and each key can point to only one value/element.
 
    SortedMap maintains mappings in ascending key order. Sorted maps are used for naturally ordered
    collections of key/value pairs
   
    Some handy collections implementations:

    ArrayList -  Resizable-array implementation of the List interface.
  
    CopyOnWriteArrayList - A thread-safe variant of ArrayList in which all mutative operations (add, set,  
    and so on) are implemented by making a fresh copy of the underlying array.
   
    Stack - Represents a last-in-first-out (LIFO) stack of objects.
   
    Vector -  Synchronized growable array of objects.

    CopyOnWriteArraySet - A Set that uses an internal CopyOnWriteArrayList for all of its operations.
  
    EnumSet - A specialized Set implementation for use with enum types.
    
    HashSet - Set implementation backed by a HashMap instance.
 
    HashMap - Hash table based implementation of the Map interface which is not synchronized
    
    WeakHashMap - A hashtable-based Map implementation with weak keys. Entries will automatically be
    removed when its key is no longer in use.

    Collections Trail is still the best place for brushing up on Java Collection API.

    Collections class (Collections ending with s) consists exclusively of static methods that operate on or
    return collections -
               binarySearch methods searches the specified list for the specified object using the binary search
               algorithm.
               Sort methods sorts specified list into ascending order, according to the natural ordering of its
               elements or according to the order induced by the specified comparator.
               Synchronized methods returns synchronized (thread-safe) collection backed by the
               specified collection.
               Unmodifiable methods returns an unmodifiable view of the specified collection. 

    Iterator enables to traverse through a collection in the forward direction only, for obtaining or removing
    elements. ListIterator extends Iterator, and allows bidirectional traversal of list and also allows the
    modification of elements.

    Implementations of the Comparator interface can be used to sort/order implements in collections by
    overriding the compare method which takes in two objects.

    Implementations of the Comparable interface are used for natural or default ordering of elements.
    Ideally if you are the author of the elements being stored in a collection, then the elements can implement
    the comparable interface and compareTo method can be overridden, however if you have no control over
    the elements in a collection, comparator is the only way.     

5. Know your IO (and NIO)


    Java IO package stands for Input and Output. The java io package deals with reading data from one input
    source and writing data to some destination. Most typical data sources and destinations include -
    Files,Pipes,Network Connections,System.in, System.out.

    A program that reads data needs an Input stream or Reader. A program writes data needs an    
    Output Stream or Writer.  Java IO package is made up of Streams, Readers and Writers. Streams
    deal with raw bytes of data while Readers/Writers deal with characters.  
 
    Stream Based
            Root Abstract Classes      - InputStream  and OutputStream     
            When dealing with Arrays - ByteArrayInputStream  and ByteArrayOutputStream
            When working with Files  - FileInputStream  RandomAccessFile and FileOutputStream    
            RandomAccessFile
            When working with Pipes   - PipedInputStream and PipedOutputStream       
            When working with chunks using buffers - BufferedInputStream and BufferedOutputStream 
            When in need of filters - FilterInputStream and FilterOutputStream 
            For Object Serializations - ObjectInputStream  and ObjectOutputStream
            When working with raw data streams reading primitive Java data types from an underlying streams -
            DataInputStream and DataOutputStream

    Character Based
            Root Abstract Classes - Reader and Writer
            Bridge classes that bridge Byte streams to Character stream - InputStreamReader and 
            OutputStreamWriter  
            When dealing with Arrays - CharArrayReader and CharArrayWriter  
            When working with Files - FileReader and FileWriter
            When working with Pipes - PipedReader and PipedWriter
            When working with chunks using buffers - BufferedReader and BufferedWriter
            When working with Filters - FilterReader and FilterWriter
            When dealing with Strings - StringReader and StringWriter 
       
    Java IO Trail which gives a good overview of the IO package.  

    Java NIO Java New IO supplements the java IO API and provides  improved performance in the
    areas of buffer management, scalable network and file I/O.

    Channels and Buffers
    In contrast to byte streams and character streams in java io, nio provides channels and buffers. Program 
    read from a channel to a buffer and similarly when writing, data is written from a buffer to a channel.
        FileChannel - A channel for reading, writing, mapping, and manipulating a file.
        SocketChannel -A selectable channel for stream-oriented connecting sockets.
        ServerSocketChannel -A selectable channel for stream-oriented listening sockets.
                
        ByteBuffer - Byte buffer.
        CharBuffer - Char buffer
        DoubleBuffer - Double buffer
        FloatBuffer - Float buffer
        IntBuffer - Int Buffer
        LongBuffer - Long Buffer
        ShortBuffer - Short Buffer
 
    Asynchronous IO
    NIO supports asynchronous IO for example, when a processing thread works with a channel to read
    data into a buffer, as the channel reads data into the buffer, the thread can do something else, Once data
    is available in the buffer, the thread can continue processing same applies when writing data as well  
 
    Selectors
    A selector is an object that can monitor multiple channels for events for example - connection opened,
    data available in buffer. This way a single thread can monitor multiple channels for data.

    When using a Selector, one must register the various Channels, that this selector will monitor for events,
    then the select() method is called which will cause the method to block until there is an event ready for
    one of the channels registered.

6. Know your Threads. 


    Threads are essentially sub-processes, informally these are tasks belonging to a larger program that
    run simultaneously.A program is a process and threads are sub-processes that run in parallel to
    speed up the entire process. The thread scheduler of the CPU decides which thread to allocate CPU
    time based  on the priority of the threads.

    Program Concurrency indicates how effectively an application allows multiple jobs to run simultaneously

    Runnable should be implemented in-order to execute tasks concurrently by threads. The class must define
    a method of  no arguments called run. 

    Thread class is a thread of execution in a program. One extends the Thread class and overrides the run
    method.

    Object's wait method causes the current to wait or until another thread invokes the notify or notifyAll
    method or until the wait timeout if provided elapses.

    ThreadLocal  supports Thread-Local variables, which means each thread that accesses the variable via
    its get or set method has its own independent initialized copy of the variable. ThreadLocal instances are
    typically private static fields in classes that wish to associate state with a thread example userID.
    
    Volatile keyword used with variables is a flag to the JVM indicating that the variable can be modified by
    multiple threads. Volatile means the value of the variable will never be cached by a thread locally, all
    read  writes will go straight to the main memory.

    Synchronization means sharing of data between multiple processes or threads. However care needs to be
    taken that each thread sees the correct version of the data as multiple threads try to access this piece of
    data. Synchronized keyword is used to provide such thread safety on shared data so that only one thread
    will have access to the shared data at any given time, this is achieved by objects locks, in which an object
    acquire a lock on the shared data and is allowed to work on the shared data while other threads wait until
    the lock is released.  

    Java Synchronization mechanism has some limitations, a thread could potentially block forever waiting to
    acquire a lock on the object, which could lead to a deadlock where two or more thread block forever
    waiting on each other. 

    Multi-Threading in java is no easy piece of cake and surely not for the faint-hearted. The simplest way to
    avoid problems with concurrency is to share only immutable data between threads. Immutable data is
    data  which can not changed, or another alternative is to make defensive copies of the data being used in
    multi-threaded applications.

    The java concurrent package is what one will use most of the time when writing multi-threaded idioms for
    our applications. The concurrent package provides the following constructs.     
   
    Locks:
    To overcome synchronization limitations using the synchronized keyword, java concurrent.locks package
    contains sophisticated locking idioms.
 
    Lock objects work very much like the implicit locks used by synchronized code. As with implicit locks,
    only one thread can own a Lock object at a time. Lock objects also support a wait/notify mechanism

    The biggest advantage of Lock objects over implicit locks is their ability to back out of an attempt to
    acquire a lock. The tryLock method backs out if the lock is not available immediately or before a timeout
    expires (if specified). The lockInterruptibly method backs out if another thread sends an interrupt before
    the lock is acquired.

          Lock - Root interface of of locking implementations
           
          ReadWriteLock - Maintains a pair of associated locks, one for read-only operations and one for
          writing. The read lock may be held simultaneously by multiple reader threads, so long as there are no
          writers. The write lock is exclusive.  
           
          Conditions - Where a Lock replaces the use of synchronized methods and statements, a Condition
          replaces the use of the Object monitor methods (wait and notify). 
 
   Executors:
   Executor is an object that executes submitted Runnable tasks. Executor provides a way of decoupling
   task submission from the mechanics of how each task will be run, including details of thread use,
   scheduling, etc. An Executor is normally used instead of explicitly creating threads.

       Callable - is similar in concept to Runnable interface, which represents task to be executed.  The only
       difference is that its call() method returns a value when it is done executing.
   
       Executor - abstracts the Thread creation and executes all Runnable tasks. An Executor is normally
       used instead of explicitly creating threads. For example, rather than invoking new
       Thread(new(RunnableTask())).start() for each of a set of tasks, you might use:
       Executor executor = anExecutor;
       executor.execute(new RunnableTask1());
        
       ExecutorService - extends the Executor and is able to execute Callable tasks in addition to Runnable
       tasks. It also contains life cycle management methods. An ExecutorService can be shut down, which
       will cause it to stop accepting new tasks. After being shut down, the executor will eventually terminate,
       at which point no tasks are actively executing, no tasks are awaiting execution, and no new tasks can
       be submitted. 
        
       ScheduledExecutorService - allows us to schedule the asynchronous tasks thereby adding support
       for  delayed and periodic task execution. The schedule methods create tasks with various delays
      and return a task object that can be used to cancel or check execution. The scheduleAtFixedRate
      and scheduleWithFixedDelay methods create and execute tasks that run periodically
      until cancelled.
        
      Future - represents the result of the asynchronous task which itself could be represented as Callable.
      The ExecutorService which can execute Callable tasks returns a Future object to return the result of the
      Callable task. A Future represents the result of an asynchronous computation. Methods are provided
      to check if the computation is complete, to wait for its completion, and to retrieve the result of the
      computation.       

   Concurrent Collections:
 
   The java concurrent package provides some new additions that supplement the java collections
   framework to provide multi-threaded support for collections. 

       ConcurrentHashMap - is a hash based Map like HashMap, but it uses a different locking strategy
       that offers better concurrency and scalability. Instead of synchronizing every method on a common
       lock,  restricting access to a single thread at a time, it uses a finer-grained locking mechanism called
       lock striping. When writing to a ConcurrentHashMap only a portion of the map is locked, reads
       generally happen without any locking.

      CopyOnWriteArrayList -  is a concurrent replacement for a synchronized List that offers better
      concurrency and eliminates the need to lock or copy the collection during iteration, similarly,
      CopyOnWriteArraySet is a concurrent replacement for a synchronized Set. These allow for multiple
      concurrent reads, however during a write a brand new copy of the list/sit is created, only one write can
      occur at a time. CopyOnWrite collections makes good sense when reads outnumber the frequency of
      writes.

      BlockingQueue - is a Queue implementation supporting the first in first out (FIFO) order but with the
      added guarantee that any attempt to retrieve an item from an empty queue will block the calling thread
      until the item is ready to be retrieved. Likewise, any attempt to insert an item into a queue that is full will
      block the calling thread until space becomes available in the queue's storage. BlockingQueue neatly
      solves the problem of how to "hand off" items gathered by one thread to another thread for processing,
      without explicit concern for synchronization issues.

      SynchronousQueues - is similar to a BlockingQueue, however this queue does not have any internal
      capacity not even one. Essentially it gives us an extremely lightweight way to exchange single elements
      from one thread to another, using the blocking semantics offered by BlockingQueue.

   Atomic Variables: 

   The concurrent atomic package defines classes that support atomic operations on single variables. All
   classes have get and set methods that work like reads and writes on volatile variables.   
       AtomicBoolean           -  A boolean value that may be updated atomically.
       AtomicInteger             -  An int value that may be updated atomically.
       AtomicLong                -  A long value that may be updated atomically.
       AtomicLongArray        - A long array in which elements may be updated atomically.
       AtomicReference  - An object reference that may be updated atomically.
       AtomicIntegerArray     - An int array in which elements may be updated atomically.

  CountDown Latch: 

  Allows to co-ordinate starting and stopping of threads, this is used when several threads need to start at
  the same time and then wait at a common point for all the threads to complete. A latch is a type of trigger
  or switch, the latch is set up with a particular count value, the count is then counted down, threads will wait
  for the countdown to reach zero before continuing to perform other operations. Once reset the latch
  cannot be reset.  CountDownLatch enables a Thread or Threads to wait for completion of Children
  Threads. But there is no waiting amongst the Children until they finish each others tasks. Children may
  execute asynchronously and after their work is done will exit making a countdown.   

  CyclicBarrier:

  CyclicBarrier can be used to create a set of Children Threads if the size of the Threads created is known
  forehand. CyclicBarrier can be used to implement waiting amongst Children Threads until all of them finish.
  This is useful where parallel threads needs to perform a job which requires sequential execution. Cyclic
  barrier can be reset after all Threads are finished execution.

   Java Concurrency trail is an essential to grasp concurrency concepts.

   Concurrency Guru's Dough Lea and Brian Goetz and are masters at their craft when it comes to Java
   Concurrency.

   Victor Grazi's Java Concurrent Animated has been around for a while now and offer's an animated look
   into the internal working of concurrency.

7. Know your java/bin.


     We all know where java ,javac and javadoc is, yep under /bin/ directory of our Java installations. We use
     java, javac and javadoc directly or indirectly in our every day work, very likely through the use of some
     Java IDE's, however I am pretty sure more of us may not be aware of other goodies that come along
     with the java/bin directory.
   
     Just a few days ago, was having a discussion about WebServices and someone goes hey can you tell me
     where to download the wsimport utility tool, yep IDE's tends to spoil us sometimes. So i guess its worth
     a mention of the tools that come along under java/bin

     Following are java tools/utilities available under java/bin for (jdk1.7.0_03)   

     appletviewer - Has been from the start allows to view Applets (doubt if anyone still works with Applets).

     apt - Annotation Processing Tool. finds and executes annotation processors based on the annotations
     present in the set of specified source files being examined.
    
     extcheck - The extcheck utility checks a specified Jar file for title and version conflicts with any
     extensions installed in the JavaTM 2 SDK. Before installing an extension, you can use this utility to see if
     the same or a more recent version of the extension is already installed.
    
     idlj - Generates Java bindings from a given IDL file, where IDL is interface definition language, one can
     define interface using OMG (Object Management Groups - CORBA fame) constructs and then generate
     java bindings using idlj.

     jar - Combines multiple files into a single JAR archive file.

     jarsigner -  Generates signatures for Java ARchive (JAR) files, and verifies the signatures of signed JAR
     files.

     javah -  Produces C header files and C source files from a Java class. These files provide the connective
     glue that allow your Java and C code to interact.  

     javap - Disassembles class files, Decompiler.

     java-rmi  - Accepts RMI-over-HTTP requests and forwards them to an RMI server listening on any
     port.

     javaw -  Java Applications Launcher, similar to java, however javaw will not open a console window for
     the application.

     javaws - Java Web Start launcher command.

     jconsole - Graphical user interface is a monitoring tool that complies to the Java Management Extensions
     (JMX) specification.

     jdb - Helps you find and fix bugs in Java language programs.

     jhat - Java Heap Analysis Tool.

     jinfo - Java Configuration Info, used in core dumps and debugging info.

     jmap - Java Memory Map,

     jps - Java Virtual Machine Process Status Tool.

     jrunscript - Command line script shell. By default, JavaScript is the language used, but the -l option can
     be used to specify a different language.  This tool is experimental and may not be available in future
     versions of the JDK.
  
     jsadebugd - Attaches to a Java process or core file and acts as a debug server.

     jstack - Stack Trace.

     jstat  and jstatd- Java Virtual Machine Statistics Monitoring Tool and Daemon process. 
   
     jvisualvm - Java Virtual Machine Monitoring, Troubleshooting, and Profiling Tool.

     keytool - Key and Certificate Management Tool.

     kinit , klist and ktab Obtain and cache Kerberos ticket-granting ticket. Kerberos display entries in
     credentials cache and keytab. Kerberos key table manager.

     native2ascii - Converts a file with native-encoded characters (characters which are non-Latin 1 and
     non-Unicode) to one with Unicode-encoded characters.

     orbd - The Object Request Broker Daemon.

     pack200 - To increase server and network availability and band-width, two new compression formats
     are available to Java deployment of applications and applets: gzip and Pack200.

     policytool - Creates and modifies the external policy configuration files that define your installation's Java
     security policy. 

     rmic, rmid and  rmiregistry - RMI compiler, daemon and RMI Registry.

     schemagen - schema generator simply creates a schema file for each namespace referenced in your Java
     classes.

     serialver - The Serial Version Command. Returns the serialVersionUID for one or more classes in a
     form suitable for copying into an evolving class. When invoked with no arguments it prints a usage line.

    servertool -  Provides a command-line interface for application programmers to register, unregister,
    startup, and shutdown a persistent server.

    tnameserv - Transient Naming Service, used in conjunction with IDL and CORBA Object Request
    Broker Daemon.

    unpack200 -  JAR Unpacking tool.

    wsgen - The wsgen tool generates JAX-WS portable artifacts used in JAX-WS web services. The tool
    reads a web service endpoint implementation class (SEI) and generates all the required artifacts for web
    service deployment, and invocation.

    wsimport - The wsimport tool generates JAX-WS portable artifacts such as Service Endpoint Interface
    (SEI), Service.

    xjc - The binding compiler can be launched using the appropriate xjc shell script in the bin directory for
    your platform.

 Until next time, Thank you
 Malcolm

 Back to Java Thoughts

Wednesday, August 15, 2012

New Tech Thoughts Welcome


A warm welcome to my humble attempt at blogging....

Having spent a considerable amount of time in the technology industry (a good decade ...and counting) have gained considerable expertise in understanding and implementing technology solutions, however as the wheel keeps on turning and new technologies churning every technologist needs to keep abreast with what's emerging ..what’s cool and what not's so cool.

The Internet provides plethora of knowledge, new electronic books with a host of technology titles. Information is just a few key strokes away (big thanks to Google).  But the big dilemma...how does one keep up?

Yes we can read and understand, but as long as one does not apply by writing actual code, getting hands dirty in code, it’s quite hard to say that you got it.  So the only way to learn new technology/concepts is to try it - no other way. Taking it one step further sharing your experience in a collaborative fashion will surely aid, feedback from experts in the fields and fellow newbie’s sharing their thoughts will help the learning process.

I have spent most of my career as a Java Applications Developer primarily, working on integration applications - Java 2 Connector Architecture, integrating with CICS/IMS applications, WebServices, some UI work involving JSP, JSF, JavaScript, Web MVC frameworks Struts/Spring MVC,  Spring, PERL in the early days, good amount of design experience and database and SQL experience.

Being a technologist need to replenish my toolbox with new tools or will be obsolete like technologies that are no longer available or evolved /morphed into something new - JINI anyone…I had spent a good 2-3 months during 2002 working on a in-house project during my first stint at technology using JINI for a peer to peer application felt quite content and happy with myself then, doubt if there is any traction on it now. Technology changes and one need to keep up (pretty sure everyone knows this by now….)

Technologies that have gained a lot of traction:  Dynamic JVM languages - Groovy/Grails, Scala. Ruby/Rails, HTML5, SOA –ESB Mule/Apache ServiceMix, NoSQL Databases, Mobile Platforms – Android, new methodologies Agile/Scrum and of course Java, Java EE, Spring which are staple diet for any enterprise.  

These are all quite mature with good backing and used in production. I have a general sense and concepts about each of them, have coded  and tried some of it but not to a level to say that yes I go it.

So coming back to my humble blog, hope to share my experience as I experiment with these new technologies (new to me at least….)  via my blog – new tech thoughts, as I learn and implement concepts, share resources and codes that will help me replenish my toolbox. I attempt to write short tutorials, notes about core concepts for both old and new concepts. I hope to capture basic concepts first before diving into more concepts, as we journey in new tech thoughts.

Thanks
Malcolm