Return-Path: X-Original-To: apmail-incubator-cloudstack-dev-archive@minotaur.apache.org Delivered-To: apmail-incubator-cloudstack-dev-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id B913CD4A2 for ; Tue, 19 Feb 2013 14:49:37 +0000 (UTC) Received: (qmail 42131 invoked by uid 500); 19 Feb 2013 14:49:37 -0000 Delivered-To: apmail-incubator-cloudstack-dev-archive@incubator.apache.org Received: (qmail 42092 invoked by uid 500); 19 Feb 2013 14:49:37 -0000 Mailing-List: contact cloudstack-dev-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: cloudstack-dev@incubator.apache.org Delivered-To: mailing list cloudstack-dev@incubator.apache.org Received: (qmail 42074 invoked by uid 99); 19 Feb 2013 14:49:36 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 19 Feb 2013 14:49:36 +0000 X-ASF-Spam-Status: No, hits=-1.6 required=5.0 tests=RCVD_IN_DNSWL_MED,SPF_NEUTRAL X-Spam-Check-By: apache.org Received-SPF: neutral (nike.apache.org: local policy) Received: from [74.125.149.147] (HELO na3sys009aog122.obsmtp.com) (74.125.149.147) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 19 Feb 2013 14:49:26 +0000 Received: from mail-gh0-f200.google.com ([209.85.160.200]) (using TLSv1) by na3sys009aob122.postini.com ([74.125.148.12]) with SMTP ID DSNKUSOQ4PcRLgguMvPSJXpyDOicmj+N0crB@postini.com; Tue, 19 Feb 2013 06:49:05 PST Received: by mail-gh0-f200.google.com with SMTP id 10so5625356ghy.3 for ; Tue, 19 Feb 2013 06:49:04 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:x-received:date:from:to:subject:message-id:references :mime-version:content-type:content-disposition:in-reply-to :user-agent:x-gm-message-state; bh=34hAbwiaDH4E4yjmhsbgy68C28GgNsag344XF41M8pk=; b=TucidWactdqgn1wvmbZITsWF2hIHkkr1ZewhT5KuWpv7C7u/afJgm6wfXJY4lTgNIh I9f8YcDy4knrYLoAzq9bIfeIDtwD+lS2HXoxzppRFVZXl7t+mHIIdJxdln6EXhsBgQvP aKVXDUDDivqNFkfQB1mexo5L/6n2nVpKYlLmLp7trkmlRdtB5n2tarQX4gSA4b42gpNp jBHNr2b1jqRF5Xd5UBfjOcKziz+2I0a8lmCxZ2Wx2GmynLP3GTtPloMLRty0ELBRjnPu 695QyeViRdcWtnDStFz0qju3hOaPRSQ+xOFiOHeE6cLJHMyhYSbq6QtoFIFVzb1cHBNA LRPQ== X-Received: by 10.52.26.40 with SMTP id i8mr18171920vdg.113.1361285344271; Tue, 19 Feb 2013 06:49:04 -0800 (PST) X-Received: by 10.52.26.40 with SMTP id i8mr18171913vdg.113.1361285344179; Tue, 19 Feb 2013 06:49:04 -0800 (PST) Received: from USLT-205755.sungardas.corp ([216.203.6.11]) by mx.google.com with ESMTPS id p7sm91805785vdt.2.2013.02.19.06.49.02 (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 19 Feb 2013 06:49:03 -0800 (PST) Received: by USLT-205755.sungardas.corp (Postfix, from userid 76098887) id 3BA29F7D1612; Tue, 19 Feb 2013 09:49:11 -0500 (EST) Date: Tue, 19 Feb 2013 09:49:11 -0500 From: Chip Childers To: cloudstack-dev@incubator.apache.org Subject: Re: [DISCUSS] Decouple your code by text file(e.g XML) Message-ID: <20130219144910.GM96733@USLT-205755.sungardas.corp> References: <93099572B72EB341B81A644E134F240B012F747FE681@SJCPMAILBOX01.citrite.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <93099572B72EB341B81A644E134F240B012F747FE681@SJCPMAILBOX01.citrite.net> User-Agent: Mutt/1.5.21 (2010-09-15) X-Gm-Message-State: ALoCoQnmw4BIO93rhtnQRXvOzxi5H7kBMU7k+ZjVd6ZSicTL6QL2LYiRu2SnCa1gSOMsG2rtloJaC7ncXt+mQx4lppF6IHkSEWvxSONmV3UrF7qTbOQ1fgDe4h33+kTGRKnuergr6ft1vobo+RkdNFOGcui1i80xKWUlYl2+5Qcvy/ZLx3FyLSij0hKSPn84FLd8zSngnLhY X-Virus-Checked: Checked by ClamAV on apache.org On Thu, Feb 14, 2013 at 04:24:48PM -0800, Frank Zhang wrote: > I have said too much about XML files recently, excuse me for raising this topic again, > I really want to elaborate why text (e.g XML) configuration files is so important and how > it decouples your project especially for project written by static language like java. > > Let me cite our new ApiDiscoveryService as an example(This service is very good, I use it > as example just because I encounter a small problem and the problem is a good study case > for decoupling code using text configuration files). > > The problem is: ApiDiscoveryService discovers API commands by invoking PluggableService. getCommands(). > Each plugin service needs to implement getCommands() which returns a List> including classes of > API command the plugin service supports. This is good, lots of project use similar way in plugin system. > > ManagementServerImpl is a special API service, it registers all orchestration API commands like *addHost*. Now > I have a special API called *addBaremetalHost* which inherits *addHost* adding one more field. *addBaremetalHost* > is actually handled by the same orchestration code as *addHost*(but different HostDiscover which is another story), > unfortunately, this API belongs to my Baremetal plugin that means I can't add it into ManagementServerImpl. getCommands() > because orchestration code should not have a dependency to plugin code. > > The solution is simple, I use a BaremetalManager to register *addBaremetalHost* and inject/call orchestration code to deal with it. > > However, this case shows us how compiling time dependency in static language makes your code tight coupling. > Everybody programing in java/C/C++ knows the pain of planning your project skeleton to avoid circular dependency. > One of solutions is to use text configuration file. Back to our example, ApiDiscoveryService, we can put a folder which > stores API configuration XML at a well-known place, every PluggableService has a XML file describing its API and Spring bean > name in the folder. for example: > > > > com.cloud.baremetal.manager.AddBaremetalHostCmd > some acl > Spring_bean_name_of_baremetal_manager > > > > When ApiDiscoveryService starts, it scans the folder and parses XML files to discover every api/theirs properties/owner bean. By doing this, ApiDiscoveryService/ > PluggableService/API command classes totally have no compiling time dependency, they can freely seat in any packages as long as these packages present in > classpath during runtime. To my case, I don't have to inject orchestration code in my plugin anymore, I just use a XML file to tell ApiDiscoveryService that addBaremetalHost > is taken cared by ManagementServerImpl as well though ManagementServerImpl has no knowledge about it. > > CloudStack used to have similar idea command.properties, unfortunately it's only used as ACL declaration now. > > This is a trivial example, but it reflects a truth that compiling dependency is naturally making your code tight. Many people criticize dynamic language is error-prone because it > lacks compiling time check, but as another side of coin, it's also easy to produce loose-coupling code. Thinking about OpenStack, if you were going to use Java to fork it, I am pretty > sure the compiling time dependency will drive you crazy. For instance, java-nova and java-cinder both need to know Volume that represents vm disk, now where do you define it? in java-nova? > in java-cinder? Then who depends on who? Or totally don't define any data structure, using a HashMap to transmit primitive variables, then where is beauty of compiling check? > > As we have adopted Spring that uses XML a lot in CloudStack, I suggest us taking more consideration of text configuration file when designing a new feature. it really works. > > +1 to what Frank is saying. Runtime configuration is much more flexible than compile-time scenarios! -chip