Newbie question on code reuse - using a previous project

87 visualizzazioni
Passa al primo messaggio da leggere

Hank Lenzi

da leggere,
7 lug 2019, 14:47:0007/07/19
a Eiffel Users
Hi folks --

Say I've got nice little class from another project. I now want to start a new one, but I don't want to retype that class again. I also don't want my new project to modify the files/class of my old project, as it will evolve differently. 
 
What do I do, in terms of local files? Can I just drag the old nice_working_class.e to the new project file? 

If and when I do that, then what? Do I have to put it in a new cluster?

Many thanks,

-- Hank

Jocelyn Fiat

da leggere,
7 lug 2019, 16:06:1007/07/19
a Eiffel Users
Two approaches:
- you want to reuse that class in many projects, and each update will benefit all the projects. Then you can create a library and copy that class inside (then include that new lib to any project you want). Note: usually we don't create a lib just for one class (even if this is possible).
- you just want to reuse the code implementation for a specific project (i.e copy/ paste). Then for your need, just copy the file to one of the clusters of your new project.

I hope this helps,
-- Jocelyn


--
You received this message because you are subscribed to the Google Groups "Eiffel Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to eiffel-users...@googlegroups.com.
Visit this group at https://groups.google.com/group/eiffel-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/eiffel-users/24b9cc57-4ed6-4516-8a04-20ee0c4abc3a%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

r...@amalasoft.com

da leggere,
7 lug 2019, 16:17:1407/07/19
a eiffel...@googlegroups.com
Perhaps a third, simpler, and common (perhaps too common to mention) option:
Create a cluster, not a library, and place the reusable class in it.
Just add the shared cluster to your projects' ecf files.
Good organization, and some "library-think" up front will help in the long run.  You have the option to create a library at a later date, of course.

R

Hank Lenzi

da leggere,
7 lug 2019, 23:33:0407/07/19
a Eiffel Users


Em domingo, 7 de julho de 2019 17:17:14 UTC-3, rfo escreveu:
Perhaps a third, simpler, and common (perhaps too common to mention) option:
Create a cluster, not a library, and place the reusable class in it.
Just add the shared cluster to your projects' ecf files.
Good organization, and some "library-think" up front will help in the long run.  You have the option to create a library at a later date, of course.

R

I'm kinda of confused bewtween library and clusters...
-- Hank 

Jocelyn Fiat

da leggere,
8 lug 2019, 03:26:3508/07/19
a Eiffel Users
Indeed cluster is another solution.
That brings the question: clusters vs libraries.

At first, Eiffel had only clusters and no libraries to structure a project (or set of projects).

Using cluster is a way to reuse classes, but it has annoyance, mostly related to dependencies.
Quite often, a cluster relies on one or many other clusters, so when you want to reuse a specific cluster in a project, you also need to know the other to include.
With time, cluster evolves, and sometimes one add a new dependency and thus breaks all other projects depending on this cluster.
Also using only clusters makes control on dependency quite hard, and with time project ends up including many many classes for nothing, including cycle in cluster relationship.

A solution was to have the notion of libraries. A library is, among other things, a set of clusters, externals (include, C lib, ...), options, and dependencies on other libraries. No cycle is allowed for libraries, and libraries are identified by their name and UUID, so if it is included by several libraries, it is included only once.
The notion of libraries avoid "spaghetti clusters", if a library evolves with new dependencies, the projects using this library are not broken and benefit from improvements. So this really improves code reuse.
I think it is also easier to share libraries with other people.

I am sure I am forgetting a few points, but for me, it is really about better control of dependency and improving reusability without pain.

I hope, now, you are less confused about cluster/libraries.


--
You received this message because you are subscribed to the Google Groups "Eiffel Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to eiffel-users...@googlegroups.com.
Visit this group at https://groups.google.com/group/eiffel-users.

For more options, visit https://groups.google.com/d/optout.


--
Jocelyn
------------------------------------------------------------------------
Eiffel Software
https://www.eiffel.com
Customer support: https://support.eiffel.com
User group: https://groups.google.com/forum/#!forum/eiffel-users
------------------------------------------------------------------------
Il messaggio è stato eliminato

Hank Lenzi

da leggere,
8 lug 2019, 19:12:4908/07/19
a Eiffel Users

Em segunda-feira, 8 de julho de 2019 04:26:35 UTC-3, Jocelyn Fiat escreveu:

I am sure I am forgetting a few points, but for me, it is really about better control of dependency and improving reusability without pain.

I hope, now, you are less confused about cluster/libraries.

Yes, thank you for that nice explanation! I had a "dependency hell" experience this Sunday, as I started to manually import Eiffel Loop's  EL_PLAIN_TEXT_FILE (in order to avoid the Python-required steps - because, well, let's just avoid non-Eiffel stuff if we can, right?), because, if I understand it correctly, it can work with Unicode in a better fashion than EiffelStudio's classes (as I've been asking here on this group).

Then I got to experience some of that circular dependency clutter. I got around to manually installing some parts of Gobo's library, and that illustrated your point. 

Living and learning. It's all good. The EiffelStudio tool is amazing in how far and wide you can just delve into code and sort problems out. Wow!  I am not a professional programmer (I'm a doctor, and got into Eiffel because of my interest in openEHR - so much of it has Eiffel under the surface -  and I simply cannot understand why more people aren't using it - I tried C++ - what a brain drain - and Java before - what a bore!)

-- Hank

 

Finnian Reilly

da leggere,
10 lug 2019, 05:50:4710/07/19
a Eiffel Users
Why Eiffel-Loop makes use of Python
 
Yes, thank you for that nice explanation! I had a "dependency hell" experience this Sunday, as I started to manually import Eiffel Loop's  EL_PLAIN_TEXT_FILE (in order to avoid the Python-required steps - because, well, let's just avoid non-Eiffel stuff if we can, right?)

Originally the reason I started using Python for managing C builds and Eiffel environments, wasn't because I was a fan of Python, (or even knew how to program in Python), it was because of the Scons build system.

During the course of developing Eiffel-Loop there were many C/C++ libraries that I wanted to make use of that required some method of cross platform building. For example:
vtd-xml
Expat
libid3tag
id3lib
Generally the Eiffel community were using make based tools to accomplish this sort of thing, but I have always found make and autoconf intimidating and cryptic and generally contrary to the spirit of Eiffel.

Then I discovered Scons and was immediately sold on it. It seemed very easy to understand, even though at that point I had never programmed in Python. What really blew me away was how easy it was to build a cross-platform shared library that compiles on both msvc and gcc.


SharedLibrary('foo', ['f1.c', 'f2.c', 'f3.c'])

One line, that's it.

Here you can read a full critique of make in relation to Scons

Once I got into using Scons, I discovered it was very easy to extend the system to do new things using Python. Python itself is incredibly easy to learn. You can learn the basics in an afternoon. From there I gradually created a system that makes it very easy to include and manage C libraries with Eiffel and for making installable packages.

From there I became sold on Python as a better way to manage Eiffel development environments in a cross platform manner, instead of using Windows batch scripts or Linux shell scripts. It also became my goto method of writing complex build scripts such as the one for the windows version of my software product My Ching. (See below)

Currently Python is the 3rd most popular langue on the TIOBE index, coming after Java and C.

For anyone who is reluctant to learn how to use Python or Scons, I think this is a pity, because for very little effort it will pay handsome dividends.

regards to all
Finnian

This is a Python script to build a code signed install package for 8 permutations of Windows platform, architecture and self-extracting exe localized language (English or German) The system ensures that you only have to do 1 Eiffel compile and then 4 C builds. I can't imagine  writing this with a batch script

import os, sys, ftplib, codecs
 
from distutils import dir_util
from distutils import file_util
from os import path
from subprocess import call
from optparse import OptionParser
 
from eiffel_loop.xml.xpath import XPATH_CONTEXT
from eiffel_loop.eiffel import project
 
from eiffel_loop.eiffel.ecf import EIFFEL_CONFIG_FILE, FINALIZED_BUILD
 
global g_project_dir, g_translations_xml_path, g_signer
 
class CODE_SIGNER (object):
 
   
# Initialization
   
def __init__ (self, cert_path, pfx_phrase):
       
self.cert_path = cert_path
       
self.pfx_phrase = pfx_phrase
       
self.time_stamp_url = 'http://timestamp.comodoca.com'
 
   
def sign (self, exe_path):
        base_cmd
= ['signtool', 'sign', '/f', self.cert_path, '/p', self.pfx_phrase]
        call
(base_cmd + self.middle_args () + ['/v', exe_path])
         
   
# Implementation
   
def middle_args (self):
       
pass
 
class SHA_256_SIGNER (CODE_SIGNER):
   
# Implementation
   
def middle_args (self):
        result
= ['/fd', 'sha256', '/tr', self.time_stamp_url + '/?td=sha256', '/td', 'sha256', '/as']
       
return result
 
class SHA_1_SIGNER (CODE_SIGNER):
   
# Implementation
   
def middle_args (self):
        result
= ['/t', self.time_stamp_url]
       
return result
 
def sha_sign (exe_path, dual_sign):
   
if path.exists (exe_path):
        g_signer
.get (256).sign (exe_path)
       
if dual_sign:
            g_signer
.get (1).sign (exe_path)
 
def write_ksign (file_list, dual_sign):
   
# Obsolete, use `sha_sign' instead
    variables
= {
       
'256_pfx_pass' : '',
       
'256_pfx_file' : '433A5C55736572735C66696E6E69616E5C446F63756D656E74735C4D79204368696E675C5369676E696E675C436F6D6F646F2E703132',
       
'256_Description' : '4D79204368696E67',
       
'256_DescriptionURL' : '687474703A2F2F6D796368696E672E736F667477617265',
       
'1_pfx_pass' : '',
       
'1_pfx_file' : '',
       
'1_Description' : '',
       
'1_DescriptionURL' : '',
       
'files_to_sign': '|'.join (file_list)
   
}
     path_template
= r'KSign\Hex11Software%s.ksign'
   
if dual_sign:
        variables
['1_pfx_file'] = '433A5C55736572735C66696E6E69616E5C446F63756D656E74735C4D79204368696E675C5369676E696E675C436F6D6F646F2D736861312E706678'
        variables
['1_Description'] = '4D79204368696E67'
        variables
['1_DescriptionURL'] = '687474703A2F2F6D796368696E672E736F667477617265'
        ksign_path
= path_template % '-dual-sign'
   
else:
        ksign_path
= path_template % ''
 
    f
= open (ksign_path, 'w')
    f
.write ('[Settings]\n')
   
for key in sorted (variables.keys ()):
        f
.write ('%s=%s\n' % (key, variables [key]))
    f
.close ()
 
def build_version ():
    f
= open (path.join ('build', 'version.txt'), 'r')
    result
= f.read ().rstrip ()
    f
.close ()
   
return result
 
def convert_pyxis_to_xml (pyxis_path, xml_path=None):
    xml_dir
= path.dirname (xml_path)
   
if not path.exists (xml_dir):
        dir_util
.mkpath (xml_dir)
     
   
print 'curdir:', path.abspath (os.curdir)
 
    cmd
= ['el_toolkit', '-pyxis_to_xml', '-in', pyxis_path]
   
if xml_path:
        cmd
.extend (['-out', xml_path])
     
   
print cmd
    call
(cmd)
 
class LOCALE (object):
 
   
# Initialization
   
def __init__ (self, xml_path, write_encoding, lang = 'en'):
       
self.translations_ctx = XPATH_CONTEXT (xml_path)
       
self.write_encoding = write_encoding
       
self.lang = lang
 
   
def languages (self):
        result
= self.translations_ctx.node_list ("//translations/item[1]/translation/@lang")
       
return result
 
   
def translation (self, item_id):
        result
= self.translations_ctx.text (
           
"/translations/item[@id='%s']/translation[@lang='%s']" % (item_id, self.lang)
       
)
       
return result
 
   
def write_translation (self, item_id, file_path):
        file_out
= open (file_path, 'w')
        file_out
.write (self.translation (item_id).encode (self.write_encoding))
        file_out
.close ()
 
   
def set_lang (self, lang):
       
self.lang = lang
 
 
def create_installer (archive_zip, locale):
    archive_exe
= path.splitext (archive_zip)[0] + '.exe'
 
    words
= path.basename (archive_exe).split ('-')
    words
.insert (1, locale.lang)
 
    locale_archive_exe
= path.join (path.dirname (archive_zip), '-'.join (words))
 
   
for exe in [archive_exe, locale_archive_exe]:
       
if path.exists (exe):
            os
.remove (exe)
 
    locale
.write_translation ('{installer-dialog-box}', 'dialog-box.txt')
    locale
.write_translation ('{unzip-installation}', 'installation.txt')
 
   
if locale.lang == 'de':
        language_option
= '-lg'
   
else:
        language_option
= '-le'
 
    make_installer_cmd
= [
       
'wzipse32', archive_zip, '-Setup', '-le', '-auto', '-runasadmin', language_option,
 
       
# Message
       
'-myesno', "installation.txt",
 
       
# Icon
       
'-i', r"resources\desktop-icons\package.ico",
 
       
# Title
       
'-st', locale.translation ('{installer-title}'),
     
       
# Dialog message
       
'-t', "dialog-box.txt",
 
       
# Installation command
       
'-o', '-c', r"package\bin\myching.exe", '-install', '-silent'
   
]
   
print
   
print 'Creating self extracting exe "%s"' % locale_archive_exe
   
print make_installer_cmd
    call
(make_installer_cmd)
 
    os
.rename (archive_exe, locale_archive_exe)
 
   
# cleanup files
   
for file_path in ['dialog-box.txt', 'installation.txt']:
       
if path.exists (file_path):
            os
.remove (file_path)
 
   
return locale_archive_exe
 
def platform_name (bit_count):
    ise_names
= {32 : 'windows', 64 : 'win64'}
   
return ise_names [bit_count]
 
def architecture (bit_count):
    names
= {32 : 'x86', 64 : 'x64'}
    result
= names [bit_count]
   
return result
 
def scons_build (args=[]):
    scons_py
= path.join (os.path.dirname (os.path.realpath (sys.executable)), 'scons.py')
    cmd
= ['python', scons_py]
   
if args:
        cmd
.extend (args)
    call
(cmd)
 
def yes_no (is_true):
   
if is_true:
        result
= 'yes'
   
else:
        result
= 'no'
   
return result
 
def build_exe (bit_count, is_xp_compatible):
   
# Build package for architecture
    scons_py
= path.join (os.path.dirname (os.path.realpath (sys.executable)), 'scons.py')
    cmd
= ['python', scons_py, 'cpu=' + architecture (bit_count), 'action=finalize']
 
   
# Don't do an Eiffel compile if any of the following (we use the F_code tar to do a C compile)
    src_root
= "source\\application_root.%s"
    compile_eiffel
= not (bit_count == 32 or is_xp_compatible or os.environ ['ISE_C_COMPILER'] == 'msc_vc140')
   
if compile_eiffel:
       
# Excluded unwanted sub applications for release
        os
.rename (src_root % "e", src_root % "developer")
        os
.rename (src_root % "release", src_root % "e")
 
    cmd
.extend (['compile_eiffel=%s' % yes_no (compile_eiffel), 'project=myching.ecf'])
    call
(cmd)
   
if compile_eiffel:
        os
.rename (src_root % "e", src_root % "release")
        os
.rename (src_root % "developer", src_root % "e")
 
def build_C_library (lib):
   
print 'Building', lib
   
# 11 Dec 2016
   
# For some reason this will not work to build elimageutils.dll even though it builds from the command line
   
# and using the Sconscript from top level build.
    scons_dir
= os.sep.join (lib.split (os.sep) [0:-3])
   
print 'cd', scons_dir
 
    os
.chdir (scons_dir)
    scons_build
()
    os
.chdir (g_project_dir)
 
def build_installers (download_path, bit_count, is_xp_compatible):
   
# build installer for each of locales
   
print 'is_xp_compatible:', is_xp_compatible
    inserts
= (bit_count, build_version ())
   
if is_xp_compatible:
        zip_name
= 'MyChing-win%d-xp-%s.zip' % inserts
   
else:
        zip_name
= 'MyChing-win%d-%s.zip' % inserts
 
    archive_zip
= path.join (download_path, zip_name)
 
    locale
= LOCALE (g_translations_xml_path, 'latin-1')
 
    os
.chdir (path.join ('build', platform_name (bit_count)))
 
   
# In directory build/win64
 
    winzip_cmd
= ['wzzip', '-a', '-rP', archive_zip, r'package\*']
 
    call
(winzip_cmd)
 
    os
.chdir (g_project_dir)
 
   
# In directory build
 
    result
= []
 
   
for lang in locale.languages ():
        locale
.set_lang (lang)
        result
.append (create_installer (archive_zip, locale))
 
   
# cleanup files
   
if path.exists (archive_zip):
        os
.remove (archive_zip)
 
   
return result
 
# SCRIPT START
 
# assign globals
g_project_dir
= path.abspath (os.curdir)
 
# Word around for bug "LookupError: unknown encoding: cp65001"
codecs
.register (lambda name: codecs.lookup ('utf-8') if name == 'cp65001' else None)
 
usage
= "usage: python build [--x86] [--upload]"
parser
= OptionParser(usage=usage)
parser
.add_option (
   
"-x", "--x86", action="store_true", dest="build_x86", default=False, help="Create a 32 bit version"
)
parser
.add_option (
   
"-a", "--all", action="store_true", dest="build_all", default=False, help="Create both a 32 bit and 64 bit version"
)
parser
.add_option (
   
"-i", "--installer", action="store_true", dest="build_installer", default=False, help="Create an installer package"
)
parser
.add_option (
   
"-e", "--exe", action="store_true", dest="build_exe", default=False, help="Build package directory with executable"
)
parser
.add_option (
   
"-p", "--xp", action="store_true", dest="is_xp_compatible", default=False, help="Build XP compatible executable"
)
(options, args) = parser.parse_args()
 
if options.build_all:
    architecture_bits
= [64, 32]
elif options.build_x86:
    architecture_bits
= [32]
else:
    architecture_bits
= [64]
 
if options.build_exe or options.build_installer:
    pfx_phrase
= raw_input ("Comodo pass phrase: ")
    cert_dir
= path.expanduser (r'~\Documents\My Ching\Signing')
    g_signer
= {
       
1 : SHA_1_SIGNER (path.join (cert_dir, 'Comodo-sha1.pfx'), pfx_phrase),
       
256 : SHA_256_SIGNER (path.join (cert_dir, 'Comodo.p12'), pfx_phrase)
   
}
else:
    g_signer
= {}
 
if options.build_exe:
   
# Update project.py build_number for `source/build_info.e'
         
   
if 64 in architecture_bits and not options.is_xp_compatible:
        project
.increment_build_number ()
 
   
for bit_count in architecture_bits:
        myching_exe_path
= r'build\%s\package\bin\myching.exe' % platform_name (bit_count)
       
if options.is_xp_compatible and path.exists (myching_exe_path):
            os
.remove (myching_exe_path)
        build_exe
(bit_count, options.is_xp_compatible)
        sha_sign
(myching_exe_path, options.is_xp_compatible)
 
if options.build_installer:
    g_translations_xml_path
= r'workarea\Installer-translations.xml'
    convert_pyxis_to_xml
(r'localization\installer.pyx', g_translations_xml_path)
 
    download_path
= path.normpath (path.dirname (g_project_dir) + "/myching-server/www/download")
 
    exe_list
= []
   
for bit_count in architecture_bits:
        installer_versions
= build_installers (download_path, bit_count, options.is_xp_compatible)
       
for install_exe in installer_versions:
            sha_sign
(install_exe, options.is_xp_compatible)
 
    os
.remove (g_translations_xml_path)
 
s
= raw_input ('Return to finish')


 


Eric Bezault

da leggere,
10 lug 2019, 10:50:3010/07/19
a eiffel...@googlegroups.com, Finnian Reilly
On 10/07/2019 11:50, Finnian Reilly wrote:
> This is a Python script to build a code signed install package for 8
> permutations of Windows platform, architecture and self-extracting exe
> localized language (English or German) The system ensures that you only
> have to do 1 Eiffel compile and then 4 C builds. I can't imagine
> writing this with a batch script

Would you imagine writing this in Eiffel (apart from the fact that
Eiffel is compiled and not interpreted)?

--
Eric Bezault
mailto:er...@gobosoft.com
http://www.gobosoft.com

Finnian Reilly

da leggere,
10 lug 2019, 11:31:2710/07/19
a Eiffel Users
Would you imagine writing this in Eiffel?

> This is a Python script to build a code signed install package for 8
> permutations of Windows platform, architecture and self-extracting exe
> localized language (English or German) The system ensures that you only
> have to do 1 Eiffel compile and then 4 C builds. I can't imagine  
> writing this with a batch script

Would you imagine writing this in Eiffel (apart from the fact that
Eiffel is compiled and not interpreted)?

Yes certainly I could imagine writing this in Eiffel, as I often use Eiffel for development related tasks. I tend to make them sub-apps of the application I am developing so it minimizes the (time) cost of creating them. If I were going to make this particular script general purpose, I would most likely rewrite it in Eiffel. But since it was created ad-hoc, Python suited.This for example is the application root for My Ching. Only the first 3 sub apps are included in the production build. The rest are miscellaneous development aids.

class
   APPLICATION_ROOT

inherit
   EL_MULTI_APPLICATION_ROOT
[BUILD_INFO]
      redefine
         
Select_first
     
end

create
   make

feature
{NONE} -- Implementation

   
Application_types: ARRAY [TYPE [EL_SUB_APPLICATION]]
         
--
      once
         
Result := <<
--          Release apps
           
{MY_CHING_APP},
           
{INSTALLER_APP},
           
{UNINSTALL_APP},

--          Development apps        
           
{ACTIVATOR_TEST_APP},
           
{AUTOTEST_DEVELOPMENT_APP},
           
{CREATE_SAMPLE_JOURNALS_APP},
           
{COMPILE_CHINESE_NAMES_APP},
           
{HELP_VIEWER_TEST_APP},
           
{MIGRATE_128_TO_256_APP},

--          Testing
           
{TEST_APP},
           
{UI_TEST_APP},
           
{REGRESSION_TEST_APP},

           
{HTML_FORECAST_APP},
           
{VERIFY_ONLINE_RESOURCES_APP}
         
>>
     
end

feature
{NONE} -- Constants

   
Select_first: BOOLEAN = True

end






Finnian Reilly

da leggere,
10 lug 2019, 11:32:1610/07/19
a Eiffel Users
Would you imagine writing this in Eiffel?

> This is a Python script to build a code signed install package for 8
> permutations of Windows platform, architecture and self-extracting exe
> localized language (English or German) The system ensures that you only
> have to do 1 Eiffel compile and then 4 C builds. I can't imagine  
> writing this with a batch script

Would you imagine writing this in Eiffel (apart from the fact that
Eiffel is compiled and not interpreted)?

Hank Lenzi

da leggere,
12 lug 2019, 10:21:5612/07/19
a Eiffel Users

For anyone who is reluctant to learn how to use Python or Scons, I think this is a pity, because for very little effort it will pay handsome dividends.

Makes sense. When I saw Python, I became reluctant, as Python is not even a stable language. 

The TIOBE index doesn't mean much IMHO (it does for jobs). BTW, I recently checked it, looking for Eiffel. I wrote them about why do they not publish its stats, they answered that it is just statistical noise, bu it is down to 250.. .The same applies to, say, Standard ML, an important language, that fostered many good ideas and derivative languages, including F# (so, it was good enough for Microsoft to incorporate its ideas on their compiler). 

I don't really care. As I said, I'm not a professional programmer, I'm a doctor and it *is* used in healthcare, having played an enormous part, as far as I understand, in enabling the specification and toolchain of what is, to me, the potentially most revolutionary thing in Electronic Health Records - OpenEHR - which, as of today, is widely deployed (but not as much as it should be) in huge systems (like, in 80% of Norway's EHR systems, or, in one of Brazil's largest private health insurance companies), so I have this luxury of reading up on programming languages and then concluding that there's lots (well, not "lots"...) of *very* interesting options out there that are non C-oids and that seem very well designed, with great tools. Let them eat cake. Eiffel seems alright (should update the utf-8 thing, though). 

-- Hank

Finnian Reilly

da leggere,
12 lug 2019, 12:15:1312/07/19
a Eiffel Users
 

The TIOBE index doesn't mean much IMHO (it does for jobs).
I am not recommending Python as a development language, just as something useful to learn for build scripts and has the added benefit of being popular.

 
I don't really care. As I said, I'm not a professional programmer,

Understood, but in any case it's not necessary to know how to program in Python in order to use Eiffel-Loop. It's just something there in the background as a facilitator, the same as the C compiler.

Hank Lenzi

da leggere,
17 lug 2019, 21:16:4117/07/19
a Eiffel Users


Understood, but in any case it's not necessary to know how to program in Python in order to use Eiffel-Loop. It's just something there in the background as a facilitator, the same as the C compiler.

I get your point (Python, instead of Make). Good point. 

Larry Rix

da leggere,
10 ago 2019, 08:42:5110/08/19
a Eiffel Users
Hi Hank,

As the others have responded, there is a cluster option and a library option.

Myself—I tend to the library option, creating many small specialized libraries.

I do this in a step-wise fashion—creating a cluster within my project to start and then migrating that cluster out into a library. The cluster I create is not a stand-alone that I add to my project, but a cluster (folder) within my project. Honestly—I have never used a stand-alone cluster in a real-world project.

Why?

For me—the issue revolves around testing. Between the Code Analyzer and the tests that I write against my code, these are the tools I depend upon to first prove my code works and then to prove that I can break my code sufficiently to then fix what I break, thereby making it more robust and dependable.

So—the question is not just "where-do-I-put-my-code"—library or cluster. The question is—my tests MUST be a part of that package—cluster or library—and where is the best and most on-going useful place to store them? I opt for a library!

Why?

Libraries completely isolate my code and their respective tests (proofs that they work and robustness tests). The best place to story both code and tests is in a library.

Why make them small?

Smaller is easier to manage at the library level. However, never too small because too small then drives me into "library hell", where I have too many libraries to manage and remember, "What does this do?" So, finding the balance of "collected purpose" (i.e. this is why these classes are grouped together in a cluster or library) is key.

So—a cluster within my project is a temporary place to collect like-purposed classes. One could also create a matching test cluster, which contains the test classes related to the code cluster classes. If I then later decide to carve them out to their own library because I want to reuse them in another project, I am all set. All I have to do is migrate both class cluster and tests to the new project. I then add that library back to the source project from which I took them and the source project is none-the-wiser. It just works.

Conclusion—for me it is not just about managing the collection of class code, but also the related proving and robustness tests that go with them.

Larry

Curly

da leggere,
13 ago 2019, 06:22:2913/08/19
a Eiffel Users
Slightly OT (a regular occurrence with me), I often find myself wanting to make a variant of a project, and it would be handy if there was a way to 'copy & rename' a project in a couple of clicks (assuming I haven't missed this option somewhere). At the moment I do this by creating a new project and umpteen classes and have to copy and paste the contents of each from the original. It is a considerable pain, and there ought to be an easier way.

r...@amalasoft.com

da leggere,
13 ago 2019, 07:07:4613/08/19
a eiffel...@googlegroups.com
Happens all the time. Well, it happens.
First, you should organize your originating project into what is, and isn't reusable.  This is always a good exercise and leads to a more robust (read: compulsive) class-oriented/reusable-component mindset, from which you will not likely ever recover.
The reorganization/refactoring will likely continue indefinitely, but with decreasing frequency and scope.
Next, break out the reusable components into separate clusters and/or libraries (see earlier thread on that topic).
Once that organization is in place, it should be  a simple matter of renaming the project in the .ecf file, and resetting any project-specific paths (there should be very few of the latter).
I developed a few conventions/protocols for the way I do things with this sort of process in mind.  These include a projects folder structure that minimizes the handwork.  Simple things that eliminate any of the unnecessary repetition.
I did, at one time, go so far as to create a project that creates projects, but I got over it :)
R

-------- Original Message --------
Subject: [eiffel-users] Re: Newbie question on code reuse - using a
previous project
--
You received this message because you are subscribed to the Google Groups "Eiffel Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to eiffel-users...@googlegroups.com.

Larry Rix

da leggere,
13 ago 2019, 08:40:0713/08/19
a Eiffel Users
Together with good project organization and the appropriate culling out of classes into small libraries—one also has the notion of project "targets".

I have a tool that I built for myself that creates a new project with a minimum of two targets—a primary project target and a test target.

What does a target do for you? it allows you to isolate "purpose" and "scope". For example—in my case, my "primary project target" has the purpose of being my finished deliverable. It's scope does NOT include classes from my testing target. Therefore, in my primary project target, I have isolated not only purpose, but given proper scope to the classes it needs, hiding others that it does not need. Yet—I have but one "project" with many "targets".

Next—there is the matter of the "override". You can use this mechanism of "override" together with project targets to get to the meat of the matter you have asked about.

An override lets you create localized, in-scope, copies of the targeted class (or classes) without disturbing the original class.

For example: You find a bug in a library class that is not under your control. You see the bug. You know the fix. You want to immediately implement the fix, but you do not have the source code to be able to apply the fix yourself. What do you do? You create an "override" version of the class, which copies that class from the source library to your project, where you can implement the fix. When the library owner makes the fix on their end (someday), you can then remove and delete your "override" copy of the class.

You can also do this for your own classes. This works extremely well if you first isolate the code you wish to override in a separate library or cluster. From there, the matter is simple: Create the override of your own class in the separate library or cluster.

NOTE: Using overrides is always about temporary fixes or experimentation. It is NEVER a permanent solution. If you have two distinct implementations of the same class, then your best best is using inheritance to isolate changes in implementation to descendant classes.

Hope this helps

L

Finnian Reilly

da leggere,
13 ago 2019, 14:20:5413/08/19
a Eiffel Users


 At the moment I do this by creating a new project and umpteen classes and have to copy and paste the contents of each from the original. It is a considerable pain, and there ought to be an easier way.

This is precisely why I created the Eiffel-Loop Multi-Application Management library. Think of it as a library for creating "Swiss-army knife applications". Visit the link for details.

You inherit EL_MULTI_APPLICATION_ROOT in your root class. An example of it's use in the root class of project toolkit.ecf: APPLICATION_ROOT

Note: currently Eiffel-loop only compiles on version 16.05 of EiffelStudio

Curly

da leggere,
15 ago 2019, 05:08:5615/08/19
a Eiffel Users
Thanks for the input, guys.

In my case I frequently have several 'experimental' applications, and rarely have a finished 'primary' from which to base the others. I tend to pick the last variant that is closest to my next idea and work from there. I do also have classes that rarely change, and really ought to move those out for reuse.

I'll take a look at your library, Finnian; thanks for the link.

Saša Janiška

da leggere,
16 set 2019, 03:54:1216/09/19
a eiffel...@googlegroups.com
On Fri, 12 Jul 2019 07:21:56 -0700 (PDT)
Hank Lenzi <hank....@gmail.com> wrote:

Hello Hank,

> I don't really care. As I said, I'm not a professional programmer,
> I'm a doctor and it *is* used in healthcare...

Just want to say I'm glad seeing that Eiffel is used by field experts and not
only by professional programmers since I am also not the one (but not the
other as well). ;)


Sincerely,
Saša

--
Therefore, without being attached to the fruits of activities,
one should act as a matter of duty, for by working without
attachment one attains the Supreme.


Saša Janiška

da leggere,
16 set 2019, 03:54:1216/09/19
a eiffel...@googlegroups.com
On Wed, 10 Jul 2019 02:50:47 -0700 (PDT)
Finnian Reilly <frei...@gmail.com> wrote:

> Originally the reason I started using Python for managing C builds
> and Eiffel environments, wasn't because I was a fan of Python, (or
> even knew how to program in Python), it was because of the Scons
> <https://www.scons.org/> build system.

I just wonder if your or someone else tried some other build systems like
CMake, waf, Meson...?

> Generally the Eiffel community were using *make* based tools to
> accomplish this sort of thing, but I have always found *make *and*
> autoconf* intimidating and cryptic and generally contrary to the
> spirit of Eiffel.

I tend to agree that there are better options than make/autoconf. :-)

> What really blew me away was how easy it was to build a cross-platform shared
> library that compiles on both msvc and gcc.

The project which I'm thinking about (to possible realize using Eiffel) would
also be cross-platform and build system should build shared library (and Eiffel
bindings) for 3rd party C library.

> From there I gradually created a system that makes it very easy to include
> and manage C libraries with Eiffel and for making installable packages.

I'd also like to produce installable packages...have you tried e.g. CMake (its
syntax is not, I agree, very pretty.)? :-)


Sincerely,
Saša

--
Abandoning all attachment to the results of his activities,
ever satisfied and independent, he performs no fruitive action,
although engaged in all kinds of undertakings.


Finnian Reilly

da leggere,
16 set 2019, 11:09:4416/09/19
a Eiffel Users


I'd also like to produce installable packages...have you tried e.g. CMake (its
syntax is not, I agree, very pretty.)? :-)


Hi Saša,
I guess you are addressing this question to me?

I haven't tried CMake, but it's possible to make install-able packages using a combination of these three things
  1. The Eiffel-Loop package-build system (just a directory structure)
  2. The Eiffel-Loop cross-platform self-installing exe system
  3. The Winzip self-extracting exe building tool (Currently I only have a custom python script to do this. Ideally I would like to use a readily available Windows tool to do this instead of winzip)
I haven't figured out yet a good equivalent to winzip self-extract on Linux but for the time being I am using tar.gz and an install script, which you have already seen an example of. But Linux has lots of installer systems that could be leveraged.

regards
Finnian

 
Sincerely,
Saša
Rispondi a tutti
Rispondi all'autore
Inoltra
0 nuovi messaggi